why items are not loading in blog.vue? - laravel

I am loading template from blog.vue in app.js, but with this it displays only header row of table not table rows as ajax call is not made.
If i comment require('./bootstrap');, it does not display table header, ajax is called but no data is displayed in table rows.
1. blog.vue file
<template>
<div class="table-responsive">
<table class="table table-borderless">
<tr>
<th>Title</th>
<th>Description</th>
</tr>
<tr v-for="item in items">
<td>#{{ item.title }}</td>
<td>#{{ item.description }}</td>
</tr>
</table>
</div>
</template>
<script>
export default {
mounted() {
console.log('Component ready.')
}
}
</script>
2. app.js file
require('./bootstrap');
Vue.component('list-blog', require('./components/blog.vue'));
new Vue({
el :'#manage-vue',
data :{
items: [],
newItem : {'title':'','description':''},
fillItem : {'title':'','description':'','id':''}
},
ready: function() {
this.getVueItems();
},
methods: {
getVueItems: function() {
this.$http.get('/vueitems?page='+page).then((response) => {
this.$set('items', response.data.data.data);
this.$set('pagination', response.data.pagination);
});
},
}
});
3. bootstrap.js
window._ = require('lodash');
window.$ = window.jQuery = require('jquery');
require('bootstrap-sass');
window.Vue = require('vue');
require('vue-resource');
Vue.http.interceptors.push((request, next) => {
request.headers.set('X-CSRF-TOKEN', Laravel.csrfToken);
next();
});
Can you please tell me where am i wrong in this ? i am using laravel-elixir here.

I think this should be only response.data.data
// this.$set('items', response.data.data.data);
// to
this.$set('items', response.data.data);
You could even simplify this
this.$http.get('/vueitems?page='+page).then((response) => {
this.items = response.data.data;
this.pagination = response.data.pagination;
}.bind(this)); // important bind(this)
It seems like you are returning a paginated object. Therefore the third data is false - isn't it?
Also you would usually pass the items to the component as property. Simply define the prop at your blog.vue
<script>
export default {
props: ['items'],
mounted() {
console.log('Component ready.')
}
}
</script>
And then pass it whereever you use it
<list-blog :items="items"></list-blog>
I highly recommend to use Chrome and the Vue devtools https://github.com/vuejs/vue-devtools - these will help you to follow and undestand the data bindings
Another smaller thing is that you shouldn't bind the pagination object AND the items seperatly. The pagination object contains the items. If you don't want o use "pagination.data" in your templates simply use a computed property instead of creating two sources of truth.

Related

Why I can't see my props from backend in my nuxt page?

I'm making an index page nad I have to recover from my db customers data and insert it in a table element in my index page.
I've set my props, mounted function with axios that get the data from the backend route and in a data function I return customers array,
my index.vue page:
<template>
<div>
<table v-if="customers">
<tr>
<th>name</th>
<th>address</th>
</tr>
<tr>
<td>{{ customers.name }}</td>
<td>{{ customers.address }}</td>
</tr>
</table>
</div>
</template>
<script>
import Table from "../components/Table.vue";
export default {
components: { Table },
name: "IndexPage",
data() {
return {
customers: [],
};
},
props: {
customer: {
required: true,
type: Object,
},
},
async mounted() {
const response = await this.$axios.$get("/api/customers");
this.customers = response.data;
},
};
</script>
if I write {{ customers }} the function return the list of customers fields but when I search for a specific data (for example {{ customers.name }}) it don't return me nothing, even errors.
Obviously I've set baseurl in nuxt.config with address of my laravel app

data is not passing in vue template although the json array is in vue page

I am using axios to get data from laravel API. I am getting the API data in my corresponding vue page (in created() hook), but it's not passing into the template. I am sharing the console Image here :
My codes from vue are :
export default {
name : "employee-list",
data() {
return{
employee_list : []
}
},
async created() {
const res = await axios.get('/employees-list')
if(res.status == 200){
console.log(res.data)
this.employee_list = res.data
}else{
console.log('something went wrong')
}
}
}
My Template table :
<table class="employee-list">
<tr>
<td>Full Name</td>
<td>Email</td>
<td>Phone</td>
<td>Designation</td>
<td>Loans</td>
<td>Salary</td>
<td>Joining Date</td>
<td>Address</td>
<td>Photo</td>
<td>Status</td>
<td>Action</td>
</tr>
<tr v-for="(employee, i) in employee_list" :key="i">
<td>{{employee.full_name}}</td>
<td>{{employee.email}}</td>
<td>{{employee.phone}}</td>
<td>{{employee.designation}}</td>
<td>{{employee.loans}}</td>
<td>{{employee.salary}}</td>
<td>{{employee.joining_date}}</td>
<td>{{employee.address}}</td>
<td>{{employee.photo}}</td>
<td>{{employee.status}}</td>
<td><button :id="employee.id">Edit</button></td>
</tr>
</table>
I also tried with callApi() method, But it says "this.callApi is not a function"
It seems there is a double array in res.data, instead of one, thats why you see one row without data

How i can send ajax request after render vue component?

I have a component
html:
table
tr(is="trcom" v-for="xml in xmls" :xml="xml")
js:
components: {
trcom: {
props: ['xml'],
template: "<tr><td> {{ xml.query }} </td><td> downloading </td><td> downloading </td></tr>",
data: function(){
return {
position: "",
}
}
}
}
can i send ajax request and replace template if ajax is done?
final template:
<tr><td> {{ xml.query }} </td> <td> {{ position }} </td> ...etc... </tr>
Given our discussion in the comments below your question, I have a recommendation:
1) The elements that you're adding and want replaced after individual ajax calls should each be their own component.
2) Because you will be using individual child components, you should use the mounted lifecycle hook to perform your ajax calls.
3) Instead of "replacing" the components' templates, which I'm not sure is even possible, you can instead use conditional rendering to show an initial state vs. a post-ajax state.
Below is a toy example which also uses jQuery (the jQuery itself isn't necessary but is being used for simplicity):
Child Component
Vue.component('my-child-component', {
template: `
<div>
<div v-if="initialized">
I'm initialized! My prop value is: {{my_prop}}
</div>
<div v-else>
I'm not initialized yet!
</div>
</div>
`,
props: ['my_prop'],
data: function() {
return {
initialized: false
};
},
mounted: function() {
//needed because we can't use "this" to reference the vue instance in our ajax call!
var this_vue_instance = this;
//this jQuery ajax call will execute as soon as this component has finished rendering
$.post('/your/target/url', {any_data: 'you might need'}, function(data) {
this_vue.initialized = true;
});
}
});
Root Vue Instance
<script>
$(document).ready(function() {
var root_vue_instance = new Vue({
el: '#app',
data: {
items: [0, 1, 2, 3]
}
});
});
</script>
<div id="app">
<div v-for="item in items">
<my-child-component :my_prop="item"></my-child-component>
</div>
</div>
The above is really bare-bones, but should server as a helpful example for implementing the solution to your current problem.

Vue not rendering my data

I have a component that I get data on create with ajax and I show this in a Template. Basically I have this:
my Vue code:
Vue.component('feedback-table', {
template: '#grid-template',
data: function () {
return {
chancesOfApproval:[],
}
},
created:function(){
$.getJSON('/getFeedbackQuestionsAndChances',function(data){
this.chancesOfApproval = data.chancesOfApproval;
}.bind(this));
},
});
new Vue({
el: '#feedback-wrapper',
});
And here is my template:
<template id="grid-template">
<table class="table table-bordered table-responsive table-striped">
<tr v-for="entry in chancesOfApproval">
<td>#{{ entry.position }}</td>
</tr>
</table>
</template>
<div id="feedback-wrapper">
<feedback-table></feedback-table>
</div>
The data is being getted from the jquery because if I do console.log(this.chanceOfApproval) for example, it appears fine in the console. And I do not get any error in my console, so I have no idea why it does not work.
It behaves as expected here, where I've switched out the getJSON for a setTimeout doing the same assignment.
Vue.component('feedback-table', {
template: '#grid-template',
data: function() {
return {
chancesOfApproval: [],
}
},
created: function() {
/*
$.getJSON('/getFeedbackQuestionsAndChances', function(data) {
this.chancesOfApproval = data.chancesOfApproval;
}.bind(this));
*/
setTimeout(() => {
this.chancesOfApproval = [{
position: 1
}, {
position: 2
}];
}, 500);
},
});
new Vue({
el: '#feedback-wrapper',
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.0.3/vue.min.js"></script>
<template id="grid-template">
<table class="table table-bordered table-responsive table-striped">
<tr v-for="entry in chancesOfApproval">
<td>#{{ entry.position }}</td>
</tr>
</table>
</template>
<div id="feedback-wrapper">
<feedback-table></feedback-table>
</div>
You are using function.bind(this) to bring this from outer scope to the function scope, in your $http success handler.
Have you checked if it is not creating any issues? I am not aware of how bind is implemented. Maybe it is not allowing Vue to trigger its Reactivity System.
If you see values in console as a plain JSON object, then it is probably wrong. Vue.js modifies object params to getters / setters / observers so that it can bind to the DOM.
Alternatively, why dont you try the arrow function or using a self variable, just to see if it solves the issue?
Arrow function (ES6 and above):
created:function(){
$.getJSON('/getFeedbackQuestionsAndChances',data => {
this.chancesOfApproval = data.chancesOfApproval;
});
}
Or use a local variable:
created:function(){
var self = this; // self points to this of Vue component
$.getJSON('/getFeedbackQuestionsAndChances',function(data){
self.chancesOfApproval = data.chancesOfApproval;
});
}
Another note: instead of setTimeout(), you also have the option of Vue.nextTick() as follows:
Vue.nextTick(function () {
// DOM updated
})
or in your case:
this.$nextTick(function () {
// DOM updated
})

Sorting and Filtering ajax data using Laravel and VueJs

Current code is sorting and filtering data using vue.js. It is working fine but data is dummy, it is hardcoded. I need to get data dynamically from table using vue js and laravel. How can I get dynamic data in gridData?
JS
Vue.component('demo-grid', {
template: '#grid-template',
props: {
data: Array,
columns: Array,
filterKey: String
},
data: function () {
var sortOrders = {}
this.columns.forEach(function (key) {
sortOrders[key] = 1
})
return {
sortKey: '',
sortOrders: sortOrders
}
},
methods: {
sortBy: function (key) {
this.sortKey = key
this.sortOrders[key] = this.sortOrders[key] * -1
}
}
})
// bootstrap the demo
var demo = new Vue({
el: '#app',
data: {
searchQuery: '',
gridColumns: ['name', 'power'],
gridData: [
{ name: 'Chuck Norris', power: Infinity },
{ name: 'Bruce Lee', power: 9000 },
{ name: 'Jackie Chan', power: 7000 },
{ name: 'Jet Li', power: 8000 }
]
}
})
laravel.blade.php
#extends('layouts.app')
#section('title', 'Customers List')
#section('styles')
#endsection
#section('content')
<div class="container">
<div class="row">
<div class="col-md-10 col-md-offset-1">
<div class="panel panel-default">
<div class="panel-heading">Customers List</div>
<div class="panel-body">
<script type="text/x-template" id="grid-template">
<table class="table table-hover table-bordered">
<thead>
<tr>
<th v-for="key in columns" #click="sortBy(key)" :class="{active: sortKey == key}">#{{key | capitalize}}<span class="arrow" :class="sortOrders[key] > 0 ? 'asc' : 'dsc'"></span>
</th>
</tr>
</thead>
<tbody>
<tr v-for="entry in data | filterBy filterKey | orderBy sortKey sortOrders[sortKey]">
<td v-for="key in columns">
#{{entry[key]}}
</td>
</tr>
</tbody>
</table>
</script>
<div id="app">
<form id="search">
Search <input name="query" v-model="searchQuery">
</form>
<demo-grid :data="gridData" :columns="gridColumns" :filter-key="searchQuery"></demo-grid>
</div>
</div>
</div>
</div>
</div>
</div>
#endsection
#section('scripts')
<script src="/js/vue.js"></script>
<script src="/js/vue-resource.min.js"></script>
<script src="/js/customers.js"></script>
#endsection
You will need to do a few things.
First, in Laravel, create a new route in your routes.php file, for ex.:
Route::get('/api/fighters', 'SomeController#index');
Then in your controller (somecontroller.php), you will have a method index which will query your database table and return it as JSON data.
public function index() {
//query your database any way you like. ex:
$fighters = Fighter::all();
//assuming here that $fighters will be a collection or an array of fighters with their names and power
//when you just return this, Laravel will automatically send it out as JSON.
return $fighters;
}
Now, in Vue, your can call this route and grab the data. Using AJAX. You can use any AJAX library that you like, even jQuery. I currently use Superagent.js. Vue will work just fine with any.
So, in your Vue code, create a new method to get your data.:
methods: {
getDataFromLaravel: function() {
//assign `this` to a new variable. we will use it to access vue's data properties and methods inside our ajax callback
var self = this;
//build your ajax call here. for example with superagent.js
request.get('/api/fighters')
.end(function(err,response) {
if (response.ok) {
self.gridData = response.body;
}
else {
alert('Oh no! We have a problem!');
}
}
}
}
Then you can just call this new method using a button or anyway you like. For example, using a button click event:
<button type="button" #click="getDataFromLaravel">Get Data</button>
Or you can even just have the data loaded automatically using Vue's ready function:
// bootstrap the demo
var demo = new Vue({
el: '#app',
data: {
.... }
ready: function () {
this.getDataFromLaravel();
},
methods: {
.... }
});
Done! You now have your database data assigned to Vue's data property gridData.

Resources