0

I'm trying to update a data grid made with Vue.js but the content isn't updating properly. Here's my HTML:

<div class="col-md-10 col-10">
    <div class="row" id="grid">
        <div class="col-md-4" v-for="entry in entries">
            <div class="info_overlay">
                <div>
                    <span class="name">{{ entry.name }}</span>
                    <span class="description">{{ entry.description }}</span>
                </div>
            </div>
        </div>
    </div>
</div>

And now this my JS:

var _results = [{name: 'toto', description: "titi" }];
var app = new Vue({
  el: '#grid',
  data: {
    entries: _results
  }
})

socket.on('get_entries', function(data){
    console.log(_results); 
    console.log(data);
    // Both logs show the same result (see below)

    _results[0].description = data[0].description    // This works! The description of the 1st item is updated
    _results = data;                                 // This doesn't work

});

Now I don't know why it's not possible to update the whole array at once. I do notice in Chrome a slight difference between the logs messages although the data is the same:

  • The first one looks like this: {…}, ob: Se] 0: description: (...) name: (...)
  • The second one looks more natural: [{…}] 0: description: "A nice pet" name: "Test pet"

Is there a difference between these two?

1
  • Yes. There is a difference. _results is a global outside of Vue's control, so it's not reactive, while entries is part of the application's data, so it is reactive. Note that JavaScript array assignments are by reference, so both _results and entries reference the same individual objects. That's why changing _results[0] also changes entries[0] Commented Jun 16, 2020 at 22:01

2 Answers 2

2

As an option:

var _results = [{name: 'toto', description: "titi" }];
var app = new Vue({
  el: '#grid',
  data: {
    entries: _results
  }
})

socket.on('get_entries', function(data){
    console.log(_results); 
    console.log(data);
    // Both logs show the same result (see below)

    _results[0].description = data[0].description    // This works! The description of the 1st item is updated
    _results.splice(0, data.length, ...data);                                // This doesn't work

});

Sign up to request clarification or add additional context in comments.

1 Comment

Wow! Now that's pretty neat. Thanks for that.
1

I believe there is a way to update the entire array without the need to do additional JavaScript in order to trigger reactivity but use what Vue has to offer.

For that, you might need to put socket into created() hook with an arrow function, so we can use this to update entries.

That way we trigger the reactivity on data property directly.

import io from 'socket.io-client';
var _results = [{name: 'toto', description: "titi" }];
var app = new Vue({
  el: '#grid',
  data: {
    entries: _results,
    socket: io()
  },
  created() { 
   this.socket.on('get_entries', (data) => {  
    this.entries = data;                                 
   });
  }
})

Does that work in your case as well?

6 Comments

I couldn't use "this" because the update is done in the socket callback function so the scope is different.
You could use an arrow function instead to change the scope. I will edit my answer shortly.
What does "this" refer to in this case?
I tried your code and it doesn't work because as I suspected, "entries" is undefined in this case.
Can you try the edited code, do you still get undefined?
|

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.