Vue version: 2.6.10
Vuetify version: 1.5
I am using example data of Vuetify 1.5.16 documentation: https://v15.vuetifyjs.com/en/components/data-tables
The problem is that in editing mode array is edited (I can see that in console) but it is not shown in vuetify data table (except if I change pages back thought or I am using input fields in expanded rows).
The problem is probably somehow related with axios, because when I used just regular data array there was no problem.
I am using Vue.js and Vuetify with Django framework but probably it has no effect for this problem.
{% extends 'base.html' %}
{% block title %}Page Name{% endblock %}
{% block custom_style %}
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css" rel="stylesheet">
{% endblock %}
{% block content %}
<v-app id="app-employees">
<div v-if="isLoading">
<v-dialog v-model="isLoading" hide-overlay persistent width="300">
<v-card dark>
<v-card-text>
<h1>
<center>Loading...</center>
</h1>
<v-progress-linear indeterminate color="white" class="mb-0"></v-progress-linear>
</v-card-text>
</v-card>
</v-dialog>
</div>
<div v-else>
<template>
<v-text-field class="search_field ma-0" v-model="search" append-icon="search" label="Paieška..." single-line
hide-details>
</v-text-field>
<v-data-table disable-initial-sort no-data="Duomenys nerasti" dark :loading="isLoading" no-data-text
:headers="headers" :items="tabledata" :search="search" :expand="expand" item-key="email"
class="elevation-1" :pagination.sync="pagination" :rows-per-page-items="rowsPerPageItems">
<template v-slot:items="props">
<td>
<v-edit-dialog :return-value.sync="props.item.first_name" lazy @save="save" @cancel="cancel"
@open="open" @close="close"> <% props.item.first_name %>
<template v-slot:input>
<v-text-field v-model="props.item.first_name" label="Edit" single-line counter>
</v-text-field>
</template>
</v-edit-dialog>
</td>
<!-- <td class="text-xs-left"> <% props.item.first_name %> </td> -->
<td class="text-xs-left"><% props.item.last_name %></td>
<td class="text-xs-left"><% props.item.email %></td>
<td class="text-xs-left"><% props.item.sex %></td>
<td @click="props.expanded = !props.expanded" class="text-xs-center">
<v-icon small v-if="props.expanded==undefined">arrow_downward</v-icon>
<v-icon small v-if="props.expanded==false">arrow_downward</v-icon>
<v-icon small v-if="props.expanded==true">arrow_upward</v-icon>
</td>
<!-- <td @click="props.expanded = !props.expanded"></td> -->
<td @click="props.expanded = !props.expanded" class="text-xs-center">
<v-icon small v-if="props.expanded==undefined">arrow_downward</v-icon>
<v-icon small v-if="props.expanded==false">arrow_downward</v-icon>
<v-icon small v-if="props.expanded==true">arrow_upward</v-icon>
</td>
<!-- <td class="text-xs-left"><% props.item.workload %></td> -->
<td class="text-xs-left"><% props.item.workload_units %></td>
<td @click="props.expanded = !props.expanded" class="text-xs-center">
<v-icon small v-if="props.expanded==undefined">arrow_downward</v-icon>
<v-icon small v-if="props.expanded==false">arrow_downward</v-icon>
<v-icon small v-if="props.expanded==true">arrow_upward</v-icon>
</td>
<td class="right">
<v-checkbox primary hide-details @click.native="props.item.active=!props.item.active"
:input-value="props.item.active"></v-checkbox>
</td>
</template>
<template v-slot:expand="props">
<v-card flat>
<v-card flat="flat" color="dark">
<v-container fluid="fluid" grid-list-xl="grid-list-xl">
<v-layout row wrap>
<v-flex xs8>Position: </v-flex>
<v-flex xs4>Categories: </v-flex>
</v-layout>
<v-layout row wrap>
<v-flex xs2>
<input class="expandable" type="text" style="float:right"
v-model="props.item.position" />
</v-flex>
<v-flex xs2>
<input class="expandable" type="text" style="float:left"
v-model="props.item.workload" />
</v-flex>
<v-spacer></v-spacer>
<v-flex xs4>
<div>
<input class="expandable" type="text" v-model="props.item.categories" />
</div>
</v-flex>
</v-layout>
</v-container>
</v-card>
</v-card>
</template>
</v-data-table>
<v-snackbar v-model=" snack" :timeout="3000" :color="snackColor">
<% snackText %>
<v-btn flat @click="snack = false">Close</v-btn>
</v-snackbar>
</template>
</div>
</v-app>
{% endblock %}
{% block custom_js_back %}
<!-- development version, includes helpful console warnings -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.js"></script>
<script>
axios.defaults.xsrfCookieName = 'csrftoken';
axios.defaults.xsrfHeaderName = 'X-CSRFToken';
axios.defaults.baseURL = "http://{{ request.get_host }}/api";
var vueData = new Vue({
delimiters: ["<%", "%>"],
el: '#app-employees',
data() {
return {
isLoading: true,
ids: null,
tabledata: [
{ first_name: null, last_name: null, email: null, sex: null, position: null, workload: null, workload_units: null, categories: null, active: null },
],
expand: false,
search: '',
snack: false,
snackColor: '',
snackText: '',
max25chars: v => v.length <= 25 || 'Input too long!',
rowsPerPageItems: [30, 40, 50,
{
value: -1,
text: "All"
}],
pagination: {
rowsPerPage: 30
},
headers: [
{
text: 'Name',
sortable: true,
value: 'first_name',
},
{ text: 'Surname', value: 'last_name' },
{ text: 'email', value: 'email' },
{ text: 'gender', value: 'sex' },
{ text: 'position', value: 'position', align: 'center' },
{ text: 'workload', value: 'workload', align: 'center' },
{ text: 'units', value: 'workload_units' },
{ text: 'categories', value: 'categories', align: 'center' },
{ text: 'Activity', value: 'active', align: 'right' },
],
}
},
beforeCreate() {
const initialData = async () => {
try {
let shiftData = null;
let categorydata = null;
let employeedata = null;
let positiondata = null;
let data = [
{ first_name: null, last_name: null, email: null, sex: null, position: null, workload: null, workload_units: null, categories: null, active: null },
];
categorydata = await axios.get('/categories/' + '{{schedule.pk}}').then(response => { return response.data })
employeedata = await axios.get('/profiles/' + '{{schedule.pk}}').then(response => { return response.data })
shiftData = await axios.get('/shifts/' + '{{schedule.pk}}').then(response => { return response.data })
positiondata = await axios.get('/positions/' + '{{schedule.pk}}').then(response => { return response.data })
data = [
{ first_name: "name", last_name: "last name", email: "email", sex: "gender", position: "position", workload: "number", workload_units: "units", categories: "category", active: "active" },
{ first_name: "name", last_name: "last name", email: "email", sex: "gender", position: "position", workload: "number", workload_units: "units", categories: "category", active: "active" },
{ first_name: "name", last_name: "last name", email: "email", sex: "gender", position: "position", workload: "number", workload_units: "units", categories: "category", active: "active" },
{ first_name: "name", last_name: "last name", email: "email", sex: "gender", position: "position", workload: "number", workload_units: "units", categories: "category", active: "active" },
{ first_name: "name", last_name: "last name", email: "email", sex: "gender", position: "position", workload: "number", workload_units: "units", categories: "category", active: "active" },
];
for (let i = 0; i < data.length; i++) {
this.tabledata[i] = data[i];
}
console.log("table data: ", this.tabledata);
this.isLoading = false;
}
catch (error) {
console.log(`Loading error: ${error}`)
}
}
initialData()
},
methods: {
save() {
this.snack = true
this.snackColor = 'success'
this.snackText = 'Saved'
console.log("Išsaugota: ", this.tabledata);
},
cancel() {
this.snack = true
this.snackColor = 'error'
this.snackText = 'Cancel'
},
open() {
this.snack = true
this.snackColor = 'info'
this.snackText = 'Edit'
},
close() {
}
}
});
</script>
{% endblock custom_js_back %}