[Vuejs]-Vue.js list not updating when data changes

2πŸ‘

βœ…

There are some Caveats with arrays

Due to limitations in JavaScript, Vue cannot detect the following changes to an array:

  • When you directly set an item with the index, e.g. vm.items[indexOfItem] = newValue

  • When you modify the length of the array, e.g. vm.items.length = newLength


To overcome caveat 1, both of the following will accomplish the same as vm.items[indexOfItem] = newValue, but will also trigger state updates in the reactivity system:

Vue.set(vm.items, indexOfItem, newValue)

Or in your case

randomise: function() {
      let input = this.list;
     
      for (let i = input.length-1; i >=0; i--) {

          let randomIndex = Math.floor(Math.random()*(i+1)); 
          let itemAtIndex = input[randomIndex]; 
          
          Vue.set(input, randomIndex, input[i]); 
          Vue.set(input, i, itemAtIndex);
      }
      this.list = input;
     
    }
πŸ‘€Nermin

1πŸ‘

Here is an working example: Randomize items fiddle

Basically I changed the logic of your randomize function to this:

randomize() {
  let new_list = []
  const old_list = [...this.list] //we don't need to copy, but just to be sure for any future update

  while (new_list.length < 4) {
    const new_item = old_list[this.get_random_number()]
    const exists = new_list.findIndex(item => item.id === new_item.id)
    if (!~exists) { //if the new item does not exists in the new randomize list add it
      new_list.push(new_item)
    }
  }
  this.list = new_list //update the old list with the new one   
},
get_random_number() { //returns a random number from 0 to 3
    return Math.floor(Math.random() * 4)
}
πŸ‘€Roland

0πŸ‘

randomise: function() {   let input = this.list;
    for (let i = input.length-1; i >=0; i--) {

      let randomIndex = Math.floor(Math.random()*(i+1)); 
      let itemAtIndex = this.list[randomIndex]; 
  
      Vue.set(this.list,randomIndex,this.list[i])
      this.list[randomIndex] = this.list[i]; 
      this.list[i] = itemAtIndex;
      }   this.list = input;
      }

Array change detection is a bit tricky in Vue. Most of the in place
array methods are working as expected (i.e. doing a splice in your
$data.names array would work), but assigining values directly (i.e.
$data.names[0] = β€˜Joe’) would not update the reactively rendered
components. Depending on how you process the server side results you
might need to think about these options described in the in vue
documentation: Array Change Detection.

Some ideas to explore:

using the v-bind:key="some_id" to have better using the push to add
new elements using Vue.set(example1.items, indexOfItem, newValue)
(also mentioned by Artokun)

Source

Note that it works but im busy so i cant optimize it, but its a little bit too complicted, i Edit it further tomorrow.

πŸ‘€niclas_4

0πŸ‘

Since Vue.js has some caveats detecting array modification as other answers to this question highlight, you can just make a shallow copy of array before randomazing it:

randomise: function() {
  // make shallow copy
  let input = this.list.map(function(item) {
     return item;
  });
 
  for (let i = input.length-1; i >=0; i--) {

      let randomIndex = Math.floor(Math.random()*(i+1)); 
      let itemAtIndex = input[randomIndex]; 

      input[randomIndex] = input[i]; 
      input[i] = itemAtIndex;
  }

  this.list = input;
 
}
πŸ‘€SciFiThief

Leave a comment