I am using Vue, Vuex, and Vuetify to display courses in data-table and want in-line editing as a feature. Please see relevant component code below.
#Courses.vue
<template>
<v-data-table
:headers="headers"
:items="courses"
:search="search"
:loading="loading"
no-data-text="No Courses Available"
>
<template slot="items" slot-scope="props">
<tr>
<td>
<v-edit-dialog
:return-value.sync="props.item.title"
lazy
>
{{ props.item.title }}
<v-text-field
slot="input"
label="Enter New Course Title"
v-model="props.item.title"
single-line
counter
@keyup.enter="onUpdateCourse({ id: props.item.id, title: props.item.title})"
></v-text-field>
</v-edit-dialog>
</td>
<td>{{ props.item.category }}</td>
<td>{{ props.item.startDate | date }}</td>
<td>{{ props.item.endDate | date }}</td>
<td>{{ props.item.location }}</td>
</tr>
</template>
</v-data-table>
</template>
<script>
export default {
data() {
return {
headers: [** table headings **],
};
},
computed: {
courses() {
return this.$store.getters.courses;
},
},
methods: {
onUpdateCourse(itemToUpdate) {
debugger;
this.$store.dispatch('updateCourse', itemToUpdate);
},
},
};
</script>
It works; but I take issue with the fact that this approach alters the Vuex state directly: the only reason to dispatch(‘updateCourse’, itemToUpdate) is to update the db (firestore in this case). I would have thought it preferable to update the $store.state solely via the Vuex actions/mutations rather than have it syncing directly here.
So, my first question is: Should I take issue with this, and if not why not?
Because it was bugging me, I added a local copy of the Vuex courses array to the computed section:
localCopy() {
return this.courses.map(x => Object.assign({}, x));
},
and built the data-table using :items="localCopy"
. This allows me to update the courses from within the Vuex actions but the data table doesn’t update until I click somewhere else in the app.
So, my second question is: If this is the correct approach, how do I keep the reactivity of the component?
Thanks for any help.
(PS – When cutting and pasting code, or editing in the text box, it seems that some of the double quotes "
are unfortunately getting converted to fancy quotes “
. It is doubly unfortunate that I am dyslexic and although I have done my best to hunt them down, I literally can’t see them most of the time. Please don’t hate on me)
Vuex stores are reactive. When Vue components retrieve state from it, they will reactively and efficiently update if the store's state changes. You cannot directly mutate the store's state. The only way to change a store's state is by explicitly committing mutations.
The second key defined in the store is the mutations key. As the name suggests, it contain an object of all of the properties responsible for making changes to the state .
Mapping in Vuex enables you to bind any of the state's properties, like getters, mutations, actions, or state, to a computed property in a component and use data directly from the state. Although we can get the job done with this. $store.state.user.data.name , we can use a map helper to simplify it to this.
To not assign changes to props.item.title
, do:
.sync
in <v-edit-dialog :return-value="props.item.title"
.v-model
with :value
in <v-text-field :value="props.item.title"
.As .sync
has an implicit @return-value:update="props.item.title = $event"
and v-model
has an implicit @input="props.item.title = $event
(roughly), the above alone (removing .sync
and replacing v-model
with :value
) would stop title
from being directly modified.
To make it being modified via dispatch
also add an @input
listener that calls the dispatch: @input="onUpdateCourse({ id: props.item.id, title: props.item.title})"
.
Finally, here's how your code should look like:
<td>
<v-edit-dialog
:return-value="props.item.title"
lazy
>
{{ props.item.title }}
<v-text-field
slot="input"
label="Enter New Course Title"
:value="props.item.title"
@input="onUpdateCourse({ id: props.item.id, title: props.item.title})"
single-line
counter
@keyup.enter="onUpdateCourse({ id: props.item.id, title: props.item.title})"
></v-text-field>
</v-edit-dialog>
</td>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With