Reputation: 513
I'm trying to get data from database and populate vuetify table with laravel,vue and vuetify. With example So far I have managed to get datatable headers but when i run npm run dev it compiles normally without any errors but in the console i get this
Uncaught TypeError: items.sort is not a function at app.js:60601
And i have printed the response of the axios function in console which I use to get data from database
Promise
__proto__: Promise
[[PromiseStatus]]: "resolved"
[[PromiseValue]]: Array(2)
0: {Day: "MONDAY", RouteCode: "MO-A", RouteName: "TORRINGTON/RAJAGIRIYA",
VehicleNo: "LZ-7878", DriverID: "Janaka Amarathunga", …}
1: {Day: "MONDAY", RouteCode: "MO-C", RouteName: " AHUNGALLA / KALUTHARA",
VehicleNo: null, DriverID: null, …}
length: 2
__proto__: Array(0)
app.js file
require('./bootstrap');
window.Vue = require('vue');
window.Vuetify = require('vuetify');
import Vuex from 'vuex'
import store from './store/store'
import 'vuetify/dist/vuetify.min.css'
Vue.use(Vuetify,Vuex);
Vue.component('example-component', require('./components/ExampleComponent.vue').default);
Vue.component('daily-delivery-planner', require('./components/DailyDeliveryPlanner.vue').default);
const app = new Vue({
el: '#app',
store,
});
store.js file
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
strict: true,
state: {
pagination: {
descending: true,
page: 1,
rowsPerPage: 4,
sortBy: 'fat',
totalItems: 0,
rowsPerPageItems: [1, 2, 4, 8, 16]
},
items: []
},
mutations: {
setPagination (state, payload) {
state.pagination = payload
},
_setItems (state, { items, totalItems }) {
state.items = items
Vue.set(state.pagination, 'totalItems', totalItems)
}
},
actions: {
queryItems (context) {
return new Promise((resolve, reject) => {
const { sortBy, descending, page, rowsPerPage } = context.state.pagination
setTimeout(() => {
let dd = getData()
console.log(dd);
let items = dd
const totalItems = items.length
if (sortBy) {
items = items.sort((a, b) => {
const sortA = a[sortBy]
const sortB = b[sortBy]
if (descending) {
if (sortA < sortB) return 1
if (sortA > sortB) return -1
return 0
} else {
if (sortA < sortB) return -1
if (sortA > sortB) return 1
return 0
}
})
}
if (rowsPerPage > 0) {
items = items.slice((page - 1) * rowsPerPage, page * rowsPerPage)
}
context.commit('_setItems', { items, totalItems })
resolve()
}, 1000)
})
}
},
getters: {
loading (state) {
return state.loading
},
pagination (state) {
return state.pagination
},
items (state) {
return state.items
}
}
})
async function getData() {
try {
const response = await axios.get('getDayRelatedData/'+'Monday');
return response.data;
} catch (error) {
console.error(error);
}
}
DailyDeliveryPlanner.vue
<template>
<v-app>
<div class="page-content browse container-fluid">
<div class="row">
<div class="col-md-12">
<div class="panel panel-bordered">
<div class="panel-body">
<div class="col-md-9">
<div class="form-group row">
<label for="day" class="col-sm-1 col-form-label custom-label">Select A Day</label>
<div class="col-sm-9">
<v-btn color="info" id="Monday">Monday</v-btn>
<v-btn color="info" id="Tuesday">Tuesday</v-btn>
<v-btn color="info" id="Wednesday">Wednesday</v-btn>
<v-btn color="info" id="Thursday">Thursday</v-btn>
<v-btn color="info" id="Friday">Friday</v-btn>
<v-btn color="info" id="Saturday">Saturday</v-btn>
<v-btn color="info" id="Sunday">Sunday</v-btn>
</div>
</div>
</div>
<div class="col-md-3">
<div class="">
<h4>Route Plan Code : <span class="label label-info" id="routeplanno">{{ routeplan_no }}</span></h4>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-12">
<div class="panel panel-bordered">
<div class="panel-body">
<div class="col-md-12">
<v-data-table
must-sort
:headers="headers"
:pagination.sync="pagination"
:rows-per-page-items="pagination.rowsPerPageItems"
:total-items="pagination.totalItems"
:loading="loading"
:items="items"
class="elevation-1"
>
<template slot="items" slot-scope="props">
<td class='text-xs-right'>{{ props.item.Day }}</td>
<td class='text-xs-right'>{{ props.item.RouteCode }}</td>
<td class='text-xs-right'>{{ props.item.RouteName }}</td>
<td class='text-xs-right'>{{ props.item.VehicleNo }}</td>
<td class='text-xs-right'>{{ props.item.DriverID }}</td>
<td class='text-xs-right'>{{ props.item.Routercode1 }}</td>
<td class='text-xs-right'>{{ props.item.Routercode2 }}</td>
<td class='text-xs-right'>{{ props.item.Capacity }}</td>
<td class='text-xs-right'>{{ props.item.planned_trips_count }}</td>
<td class='text-xs-right'>{{ props.item.Trip_Count }}</td>
<td class='text-xs-right'>{{ props.item.Location }}</td>
<td class='text-xs-right'>{{ props.item.FG_Count }}</td>
<td class='text-xs-right'>{{ props.item.PET_Count }}</td>
<td class='text-xs-right'>{{ props.item.Createuser }}</td>
</template>
</v-data-table>
</div>
</div>
</div>
</div>
</div>
</div>
</v-app>
</template>
<script>
export default {
data () {
return {
loading: false,
routeplan_no:"",
headers: [
{
text: 'Day',
align: 'left',
sortable: false,
value: 'day'
},
{ text: 'Route Code', value: 'route_code' },
{ text: 'Route Name', value: 'route_name' },
{ text: 'Vehicle No', value: 'vehicle_no' },
{ text: 'Driver Name', value: 'driver_name' },
{ text: 'Router 01', value: 'router_01' },
{ text: 'Router 02', value: 'router_02' },
{ text: 'Capacity', value: 'capacity' },
{ text: 'Planned Trip Count', value: 'planned_trip_count' },
{ text: 'Trip Count', value: 'trip_count' },
{ text: 'Location', value: 'location' },
{ text: 'FG Count', value: 'fg_count' },
{ text: 'PET Count', value: 'pet_count' },
{ text: 'Created User', value: 'created_user' },
]
}
},
watch: {
pagination: {
handler () {
this.loading = true
this.$store.dispatch('queryItems')
.then(result => {
this.loading = false
})
},
deep: true
}
},
computed: {
pagination: {
get: function () {
return this.$store.getters.pagination
},
set: function (value) {
this.$store.commit('setPagination', value)
}
},
items () {
return this.$store.getters.items
}
},
methods: {
getUserData: function() {
axios.get('retreiveUserData')
.then(({data}) => {
if(data.alert=='success'){
this.routeplan_no = data.data;
}else{
this.routeplan_no = Math.floor(1000 + Math.random() * 9000);
}
});
}
},
beforeMount() {
this.getUserData();
}
}
</script>
Since I'm a beginner to vue I've followed this codepen. Is this the right approach ? Any help and suggestions would be appreciated !
Upvotes: 1
Views: 1188
Reputation: 22403
Your getData
function return a Promise. You can't sort it directly. You should use async/await
for .then()
to wait for the Promise result
actions: {
queryItems (context) {
return getData().then(dd => {
const { sortBy, descending, page, rowsPerPage } = context.state.pagination
let items = dd
const totalItems = items.length
if (sortBy) {
items = items.sort((a, b) => {
const sortA = a[sortBy]
const sortB = b[sortBy]
if (descending) {
if (sortA < sortB) return 1
if (sortA > sortB) return -1
return 0
} else {
if (sortA < sortB) return -1
if (sortA > sortB) return 1
return 0
}
})
}
if (rowsPerPage > 0) {
items = items.slice((page - 1) * rowsPerPage, page * rowsPerPage)
}
context.commit('_setItems', { items, totalItems })
})
}
}
Upvotes: 0
Reputation: 5632
why it happened:
you called asynchronous getData
from inside a synchronous function (it doesnt matter that its inside a promise). the asynchronous chain was broken.
since javaScript is running asynchronously, your items.sort
(probably) happened before the async getData
resolved, therefore, items
was still undefined
and when trying items.sort
you got the typeError.
how to solve:
asynchronous process should stay asynchronous all the way down the functions chain.
you are calling getData
, which is asynchronous, therefore, queryItems
should be asynchronous as well, so it will be able to wait for the response. i saw you are mixing promises and asyncawait so i brought here an converted queryItems
(which returning a promise) to an async function in bot ways:
using async-await
:
async queryItems (context) {
return new Promise((resolve, reject) => {
const { sortBy, descending, page, rowsPerPage } = context.state.pagination
setTimeout(async () => {
try{
let dd = await getData()
}catch{
return reject();}
console.log(dd);
let items = dd
const totalItems = items.length
if (sortBy) {
items = items.sort((a, b) => {
................................
return resolve();
}
using only promises syntax:
queryItems (context) {
return new Promise((resolve, reject) => {
const { sortBy, descending, page, rowsPerPage } = context.state.pagination
setTimeout(() => {
return getData().then(dd=>
console.log(dd);
let items = dd;
const totalItems = items.length
if (sortBy) {
items = items.sort((a, b) => {
................................
return resolve();
}).catch(e=>{
return reject(e)})
}
Upvotes: 1