Reputation: 6363
I know there is many similar questions about data not being updated in VueJS component but I still could not find the answer. I have the following component:
<template>
<div class="mt-5">
[...]
<div v-for="dataSource in dataSources" v-bind:key="dataSource.id">
{{ dataSource}}
</div>
[...]
</div>
</template>
<script>
import { chain, find, merge, toUpper } from "lodash";
import Mixins from "../utils/Mixins.vue";
import Pagination from "../utils/Pagination.vue";
import DataSourceTable from "./DataSourceTable.vue";
export default {
mixins: [Mixins],
components: {
"data-source-table": DataSourceTable,
"data-source-pagination": Pagination
},
data: function() {
return {
dataSources: [],
//[...]
};
},
methods: {
getAllDataSources(page) {
//[...]
},
search() {
//[...]
},
setSortAttribute(attribute) {
//[...]
},
updateDataSource(updatedDataSource){
for (let i = 0; i < this.dataSources.length; i++) {
if (this.dataSources[i].id == updatedDataSource.id) {
this.dataSources[i] = updatedDataSource;
break; // Stop this loop, we found it!
}
}
}
},
created: function() {
this.getAllDataSources(this.currentPage);
// Capture updated data source via websocket listener
this.$options.sockets.onmessage = function(data) {
let message = JSON.parse(data.data);
if (message.id == "dataSource" && message.type == "data") {
let updatedDataSource = message.payload.data.listen.relatedNode;
this.updateDataSource(updatedDataSource);
}
}
}
};
</script>
In the created
hook, I capture changes coming from a websocket and I update the corresponding item in the array dataSources
. I can see the item is properly updated in Vue Dev Tools but it is still not updated in the component template. Example below:
Upvotes: 1
Views: 1238
Reputation: 645
When you modify an Array by directly setting an index (e.g. arr[0] = val) or modifying its length property. Similarly, Vue.js cannot pickup these changes. Always modify arrays by using an Array instance method, or replacing it entirely. Vue provides a convenience method arr.$set(index, value) which is syntax sugar for arr.splice(index, 1, value).
updateDataSource(updatedDataSource){
for (let i = 0; i < this.dataSources.length; i++) {
if (this.dataSources[i].id == updatedDataSource.id) {
//this.dataSources[i] = updatedDataSource;
this.dataSources.$set(i, updatedDataSource);
break; // Stop this loop, we found it!
}
}
}
Upvotes: 0
Reputation: 46
This is a common mistake with vuejs. You can check the document here: Why isn’t the DOM updating? In Your case, you can use push or $set to achieve your purpose.
When you modify an Array by directly setting an index (e.g. arr[0] = val) or modifying its length property. Similarly, Vue.js cannot pickup these changes. Always modify arrays by using an Array instance method, or replacing it entirely. Vue provides a convenience method arr.$set(index, value) which is syntax sugar for arr.splice(index, 1, value).
Example:
this.dataSources[i] = updatedDataSource;
this.dataSources.splice(i, 1, updatedDataSource);
Upvotes: 3