1

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:

enter image description here

2 Answers 2

3

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:

  • Replace this.dataSources[i] = updatedDataSource;
  • By this.dataSources.splice(i, 1, updatedDataSource);
Sign up to request clarification or add additional context in comments.

Comments

0

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!
        }
      }
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.