Vue.js + vue-router + axios + Laravel. Can't retrieve values by id - laravel

Why can't get values via axios?
I get correct ID of tasks, can show it in Blade but can't get in Vue.
Where is mistake?
id = 4 - is id of task
When i try http://cosys.loc/api/task/4 - is ok, i get json of task with ID 4.
This is link for example: <router-link :to="{ name: 'TaskShow', params: { id: 4 }}">Show details</router-link>
TaskDetails.vue:
<template>
<div class="container-fluid my-3">
<h1>ID from URL: #{{ this.$route.params.id }}</h1>
<h2>taskId: {{ taskId }}</h2>
<p class="lead">{{ this.$route.tasks }}</p>
<ul>
<li>{{ tasks.id }}</li>
<li>{{ tasks.title }}</li>
<li>{{ tasks }}</li>
</ul>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: "TaskDetails",
data() {
return {
tasks: {},
taskId: this.$route.params.id,
loading: true,
errored: false,
}
},
mounted() {
axios
.get(`/api/task/${this.$route.params.id}`)
.then(response => (this.tasks = response.data.tasks), (console.log(`${this.$route.params.id}`)))
.catch(error => console.log(error))
.finally(() => (this.loading = false));
},
}
</script>
<style scoped>
</style>
When i open url http://cosys.loc/tasks/show/4 get values of tasks with ID 1.
Why, how to solve this?
Tnx,
Anton

I put together an example with two components and a router to show how to implement.
Router
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter);
import Home from '#/components/stackoverflow/router-params-example/Home'
import Detail from '#/components/stackoverflow/router-params-example/Detail'
const routes = [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/detail/:id',
name: 'detail',
component: Detail,
props: true
}
]
export default new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
Home
<template>
<div class="parent">
<h4>Home</h4>
<div class="row">
<div class="col-md-6">
<router-link class="btn btn-primary" :to="{ name: 'detail', params: { id: detailId } }">Show Detail</router-link>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
detailId: 1
}
}
}
</script>
Detail
<template>
<div class="child">
<h4>Detail</h4>
<div class="row">
<div class="col-md-6">
<table class="table table-bordered">
<thead>
<tr>
<th>ID</th>
<th>NAME</th>
<th>USER NAME</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ user.id }}</td>
<td>{{ user.name }}</td>
<td>{{ user.username }}</td>
</tr>
</tbody>
</table>
<router-link class="btn btn-secondary" :to="{ name: 'home' }">Back</router-link>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
props: {
id: {
type: Number,
required: true
}
},
data() {
return {
user: {}
}
},
methods: {
getUser() {
axios.get('https://jsonplaceholder.typicode.com/users/' + this.id)
.then( response => this.user = response.data )
.catch( error => console.log(error) )
}
},
created() {
this.getUser();
}
}
</script>

Related

app.js:10567 [Vue warn]: Component is missing template or render function

No clue where the error coming from, hours trying to find it.
All the components the same.
Configure vue router is a nightmare.
Error:
app.js:10567 [Vue warn]: Component is missing template or render
function. at <CreateProduct onVnodeUnmounted=fn
ref=Ref< undefined > > at at at
http://localhost
http://localhost/create
router.js
import AllProduct from './components/AllProduct.vue';
import CreateProduct from './components/CreateProduct.vue';
import EditProduct from './components/EditProduct.vue';
import {createWebHistory, createRouter} from "vue-router";
const routes = [
{
name: 'home',
path: '/',
component: AllProduct
},
{
name: 'create',
path: '/create',
component: CreateProduct
},
{
name: 'edit',
path: '/edit/:id',
component: EditProduct
}
];
const router = createRouter({
history: createWebHistory(),
routes: routes,
});
export default router;
app.js
require('./bootstrap');
import { createApp,h } from 'vue';
import router from './routes';
import App from './App.vue';
import axios from 'axios'
const app = createApp({ render: () => h(App) });
app.config.globalProperties.$axios = axios;
app.use(router);
app.mount('#app');
App.vue
<template>
<div class="container">
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="collapse navbar-collapse">
<div class="navbar-nav">
<router-link to="/" class="nav-item nav-link">Products List</router-link>
<router-link to="/create" class="nav-item nav-link">Create Product</router-link>
</div>
</div>
</nav>
<router-view> </router-view>
</div>
</template>
<script>
export default {}
</script>
AllProducts.vue
<template>
<div>
<h2 class="text-center">Products List</h2>
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Detail</th>
<!-- <th>Actions</th> -->
</tr>
</thead>
<tbody>
<tr v-for="product in products" :key="product.id">
<td>{{ product.id }}</td>
<td>{{ product.name }}</td>
<td>{{ product.detail }}</td>
<td>
<div class="btn-group" role="group">
<router-link :to="{name: 'edit', params: { id: product.id }}" class="btn btn-success">Edit</router-link>
<button class="btn btn-danger" #click="deleteProduct(product.id)">Delete</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
data() {
return {
products: []
}
},
created() {
this.axios
.get('/api/products/')
.then(response => {
this.products = response.data;
});
},
methods: {
deleteProduct(id) {
this.axios
.delete(`http://localhost:8000/api/products/${id}`)
.then(response => {
let i = this.products.map(data => data.id).indexOf(id);
this.products.splice(i, 1)
});
}
}
}
</script>
if you read the red error, it says cannot read propertie of undefined (reading 'get')
That means your trying to access the get propertie of an undefined object
looking for getin your code, we find :
this.axios
.get('/api/products/')
so that means this.axios is undefined
it's undefined cause you declared it like this :
app.config.globalProperties.$axios = axios;
with a $ sign

Vue js select box giving a couple of errors

I'm doing a site that uses laravel and vue js. The error I'm getting is this
[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "selected_parent"
and this
[Vue warn]: Error in v-on handler (Promise/async): "Error: Request failed with status code 404"
I can't see where I'm going wrong.
Here is my product.blade.php
#extends('layouts.public')
#section('content')
<div class="content_wrapper">
#foreach($single_product as $product)
<div class="row single_product_wrapper">
<div class="col-lg-8 col-md-12-col-sm-12 product_details">
#foreach($parent_product as $parent)
<h1>
{{ $parent->title }}
</h1>
<table style="width: 100%; height: 95px;" border="2" cellspacing="5" cellpadding="5">
<tbody>
<tr style="text-align: center;">
<td>
<strong>Code</strong>
</td>
<td>
<strong>Description</strong>
</td>
<td>
<strong>Price</strong>
</td>
</tr>
<tr style="text-align: center;">
<td>
{{ $parent->code }}
</td>
<td>
{{ $parent->description }}
</td>
<td>
{{ $parent->price }}
</td>
</tr>
</tbody>
</table>
#endforeach
<!-- BEGIN ADD TO CART FORM -->
<div id="app">
#foreach($parent_product as $parent)
<code-selection :products="{{ $parent_product }}" :children="{{ $parent->parent }}"></code-selection>
#endforeach
</div>
<!-- END ADD TO CART FORM -->
</div>
</div>
#endforeach
</div>
#stop
and this is my vue
<template>
<div>
<form #submit.prevent="submit">
<div class="row">
<div class="col-lg-12 code_select">
<select name="code" id="code" class="form-control mb-2 mt-10" v-model="selected_parent" required>
<option :value="selected_parent">Please select your code</option>
<option v-for="product in products" :value="product.id">
{{ product.code }}
</option>
<option v-for="child in children" :value="child.id">
{{ child.code }}
</option>
</select>
</div>
</div>
<input type="submit" class="btn btn-dark btn-lg btn-block" value="Add To Cart">
</form>
</div>
</template>
<script>
import axios from 'axios'
export default {
props: [
'products',
'children',
'selected_parent'
],
mounted() {
console.log('Component mounted.')
},
methods: {
submit(){
var formData = new FormData();
formData.append('code', this.selected_parent);
return axios.post('/add-to-cart/'+this.selected_parent, formData)
.then(
function(response)
{
console.log(response.data.redirect);
window.location = response.data.redirect;
}
);
},
},
}
</script>
So what I would like to happen is, when the user selects a code and hits the Add To Cart button they will then get taken to the cart page, but right now
that isn't happening when I select the code and hit the button nothing happens and I get the errors that I said in my console.
If there is anything else you need to know please let me know
The answer is simple, you should break the direct prop mutation by assigning the value to some local component variables(could be data property, computed with getters, setters, or watchers).
Here's a simple solution using the watcher.
<template>
<input
v-model="input"
#input="updateInput" />
</template>
<script>
export default {
props: {
value: {
type: String,
default: '',
},
},
data() {
return {
input: '',
};
},
watch: {
value: {
handler(after) {
this.input = after;
},
immediate: true,
},
},
methods: {
updateInput() {
this.$emit('input', this.input);
},
},
};
</script>
It's what I use to create any data input components and it works just fine. Any new variables sent by parent v-model will be watched and assigned to the input variable and once the input is received, catch that action and emit input to parent suggesting that data is input from the form element.
And for the second part, when you receive the new url from redirect, simply replace the location href like this:
return axios.post('/add-to-cart/'+this.selected_parent, formData)
.then((response) => {
window.location.href = response.data.redirect;
})
.catch((error) => {
console.log(error);
})
);

How to reload a page in laravel vue after save?

I'm trying to reload the page after save in laravel and vue.js, I do this in "fetchGoals". Here is what I've tried and it works the first time, it saves the goal and refreshes the page. When I try to add another goal then the save button no longer works and the page will not refresh. Same goes for the edit button, it will work the first time and then the second time it will not. Regardless if is save or edit, the same problem exists where I can only perform one function where the pages refreshes. Any ideas what I'm doing wrong?
<template>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">
<form #submit.prevent="addGoal" class="mb-3">
<div class="form-group">
<input type="text" class="form-control" placeholder="Goal" v-model="goal.title">
</div>
<div class="form-group">
<textarea class="form-control" placeholder="Description" v-model="goal.description">
</textarea>
</div>
<button type="submit" class="btn btn-primary btn-block">Add New Goal</button>
</form>
<button #click="clearForm()" class="btn btn-danger btn-block">Cancel</button>
<div class="panel-body">
<table class="table">
<thead>
<tr>
<th scope="col">id</th>
<th scope="col">Title</th>
<th scope="col">Description</th>
</tr>
</thead>
<tbody>
<tr v-for="goal in goals" v-bind:key="goal.id">
<td>{{goal.id}}</td>
<td>{{goal.title}}</td>
<td>{{goal.description}}</td>
<td>
<button #click="editGoal(goal)" class="btn btn-warning btn-xs">Edit</button>
</td>
<td>
<button #click="deleteGoal(goal.id)" class="btn btn-danger btn-xs">Delete
</button>
</td>
</tr>
</tbody>
</table>
<nav aria-label="Page navigation example">
<ul class="pagination">
<li v-bind:class="[{disabled: !pagination.prev_page_url}]" class="page-item">
<a class="page-link" href="#" #click="fetchGoals(pagination.prev_page_url)">Previous</a>
</li>
<li class="page-item disabled">
<a class="page-link text-dark" href="#">Page {{ pagination.current_page }} of {{
pagination.last_page }}</a>
</li>
<li v-bind:class="[{disabled: !pagination.next_page_url}]" class="page-item">
<a class="page-link" href="#"
#click="fetchGoals(pagination.next_page_url)">Next</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
goals: [],
goal: {
id: '',
title: '',
description: '',
user_id: 1,
},
goal_id: '',
pagination: {},
edit: false
};
},
created() {
this.fetchGoals();
},
methods: {
//gets the data and the pagination
fetchGoals(page_url) {
let vm = this;
page_url = page_url || '/api/goals';
fetch(page_url)
.then(res => res.json())
.then(res => {
this.goals = res.data;
//this comes from res and res is the data from the Jason
vm.makePagination(res.meta, res.links);
})
.catch(err => console.log(err));
},
addGoal() {
if (this.edit === false) {
// Add
fetch(`/api/goal`, {
method: 'post',
body: JSON.stringify(this.goal),
headers: {
'content-type': 'application/json',
}
})
.then(res => res.json())
.then(data => {
this.clearForm();
alert('Article Added');
this.fetchGoals();
})
.catch(err => console.log(err));
} else {
//Edit save
fetch(`/api/goal`, {
method: 'put',
body: JSON.stringify(this.goal),
headers: {
'content-type': 'application/json',
}
})
.then(res => res.json())
.then(data => {
this.clearForm();
alert('Article Added');
this.fetchGoals();
})
.catch(err => console.log(err));
}
},
editGoal(goal) {
this.edit = true;
this.goal.id = goal.id;
this.goal.goal_id = goal.id;
this.goal.title = goal.title;
this.goal.description = goal.description;
},
clearForm() {
this.edit = false;
this.goal.id = null;
this.goal.goal_id = null;
this.goal.title = '';
this.goal.description = '';
this.goal.user_id = null;
}
}
};
</script>
You can use traditional JavaScript to solve your problem
// Reload the current page
window.location.reload();
Use window.location.reload(true); to force reload (ignore the browser cache)

VueJs With Laravel

I am learning Vuejs. I am making a system where users can set a message as favourite.
But i am getting the below error. Any help to resolve would be appreciated.
[Vue warn]: Failed to mount component: template or render function not
defined. found in
---> Favorite Root
Below is my code =>
Favorite.vue
<template>
<span>
<a href="#" v-if="isFavorited" #click.prevent="unFavorite(post)">
<i class="fa fa-heart"></i>
</a>
<a href="#" v-else #click.prevent="favorite(post)">
<i class="fa fa-heart-o"></i>
</a>
</span>
</template>
<script>
export default {
name: 'favorite',
props: ['post', 'favorited'],
data: function() {
return {
isFavorited: '',
}
},
mounted() {
this.isFavorited = this.isFavorite ? true : false;
},
computed: {
isFavorite() {
return this.favorited;
},
},
methods: {
favorite(post) {
axios.post('/favorite/'+post)
.then(response => this.isFavorited = true)
.catch(response => console.log(response.data));
},
unFavorite(post) {
axios.post('/unfavorite/'+post)
.then(response => this.isFavorited = false)
.catch(response => console.log(response.data));
}
}
};
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
app.js
require('./bootstrap');
window.Vue = require('vue');
/**
* Next, we will create a fresh Vue application instance and attach it to
* the page. Then, you may begin adding components to this application
* or customize the JavaScript scaffolding to fit your unique needs.
*/
Vue.component('Favorite', require('./components/Favorite.vue'));
const app = new Vue({
el: '#app'
});
index.blade.php
#extends('layouts.app')
#section('content')
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel">
<h3>All Posts</h3>
<hr>
</div>
#forelse ($posts as $post)
<div class="card">
<div class="card-header">
{{ $post->title }}
</div>
<div class="card-body mb-2">
{{ $post->body }}
</div>
#if (Auth::check())
<div class="card-footer mb-2">
<favorite
:post={{ $post->id }}
:favorited={{ $post->favorited() ? 'true' : 'false' }}
></favorite>
</div>
#endif
</div>
#empty
<p>No post created.</p>
#endforelse
{{ $posts->links() }}
</div>
</div>
</div>
#endsection
Try Vue.component('Favorite', require('./components/Favorite.vue').default); with .default at the end.

Pagination problems in Vue and Laravel

Here is a component I've made for my Vue app within a laravel project.
<template>
<div>
<h2 class="text-center mt-3 mb-5">Categories</h2>
<form v-on:submit.prevent="addCategory">
<div class="row">
<div class="col-2"></div>
<div class="col-md-6">
<div class="form-group">
<input type="text" class="form-control" v-model="name.name">
</div>
</div>
<div col-2>
<button class="ml-5 btn btn-primary" v-on:submit.prevent="addCategory">Add New Tag</button>
</div>
<div class="col-2"></div>
</div>
</form>
<div class="row">
<div class="col-2"></div>
<div class="col-md-8">
<br/>
<table class="table table-hover">
<thead>
<tr class="alert-info">
<td>ID</td>
<td>Category Name</td>
<td style="width: 25%">Actions</td>
</tr>
</thead>
<tbody>
<tr v-for="category in categories.data">
<td>{{ category.id }}</td>
<td>{{ category.name }}</td>
<td>
<router-link :to="{name: 'EditCategory', params: { id: category.id }}"
class="btn btn-primary btn-sm ml-auto">Edit
</router-link>
<button class="btn btn-danger btn-sm" v-on:click="deleteCategory(category.id)">Delete
</button>
</td>
</tr>
</tbody>
</table>
<vue-pagination :pagination="categories" #paginate="fetchCategories()" :offset="4"></vue-pagination>
<hr class="custom-hr-divider"/>
</div>
<div class="col-2"></div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
categories:{
total: 0,
per_page: 2,
from: 1,
to: 0,
current_page: 1
},
name: {}
}
},
created: function () {
this.fetchCategories();
},
components:{
VuePagination: require('../components/Pagination.vue')
},
methods: {
fetchCategories() {
this.axios.get('/categories/index?page=' + this.current_page)
.then(function (response) {
this.users = response.data.data;
this.pagination = response.data;
})
.catch(() => {
console.log('handle server error from here');
});
},
deleteCategory(id) {
let uri = `http://localhost:8000/categories/delete/${id}`;
this.axios.delete(uri);
this.fetchCategories();
},
addCategory() {
let uri = 'http://localhost:8000/categories';
this.axios.post(uri, this.name).then((response) => {
this.fetchCategories();
this.name = {};
})
}
}
};
</script>
Here is the Pagination.vue file I found in an online tutorial.
My app works fine without pagination but introducing this code causes the following errors.
***[Vue warn]: Failed to mount component: template or render function not defined.
found in
---> <VuePagination>
<DisplayCategory> at resources\assets\js\components\DisplayCategory.vue
<Root>***
Where do I define define the component? Ive been trying to get this to work for hours.
app.js
import Vue from 'vue';
import VueRouter from 'vue-router';
Vue.use(VueRouter);
import VueAxios from 'vue-axios';
import axios from 'axios';
Vue.use(VueAxios, axios);
import App from './App.vue';
import DisplayTag from './components/DisplayTag.vue';
import EditTag from './components/EditTag.vue';
import DisplayCategory from './components/DisplayCategory.vue';
import EditCategory from './components/EditCategory.vue';
const routes = [
{
name: 'DisplayTag',
path: '/tags',
component: DisplayTag
},
{
name: 'EditTag',
path: '/tags/edit/:id',
component: EditTag
},
{
name: 'DisplayCategory',
path: '/categories',
component: DisplayCategory
},
{
name: 'EditCategory',
path: '/categories/edit/:id',
component: EditCategory
}
];
const router = new VueRouter({ mode: 'history', routes: routes});
new Vue(Vue.util.extend({ router }, App)).$mount('#app');
Anyone with any ideas what I'm doing wrong?
Thanks in advance.
Achieved pagination by using laravel-vue-pagination
Getting started is easy to follow and I only had to change 1 line as I am using axios.
fetchCategories(page) {
if (typeof page === 'undefined') {
page = 1;
}
// Using vue-resource as an example
let uri = `http://localhost:8000/categories/index?page=`;
this.axios.get(uri + page).then((response) =>
{this.categories = response.data;})

Resources