2

I've declared my data object as queuedItemList: [] which is supposed to contain an array of items provided by a background service. After the HTTP request, I populate the list using a for loop like

for(var i = 0; i < getList.length; i++) {
    var newObject = Object.assign({}, getList[i]);
    this.queuedItemList.splice(i, 1, newObject);
}

which is used to populate the following template

<Item v-for="(item, index) in queuedItemList" :key="index" :componentData="item" :index="index" @remove="removeItem">
</Item>

I am supposed to do a periodic HTTP GET to get the new list of items, which may also contain current items with maybe different state. Inside the component, I am using a v-if to select between two different icons.

<v-icon name="play" class="controlIcons" v-if ="playControl" />
<v-icon name="pause" class="controlIcons" v-if ="!playControl" />

Now, after some HTTP requests, I see the value of playControl change in Vue Devtools which confirms that the actual value is reflected in the component. However, I can't see the icons change due to the change in the value of playControl. Furthermore, everything works as expected if I refresh the screen.

My guess is that I'm messing up the reactivity somewhere. Thanks!

4 Answers 4

7

You're looking for https://v2.vuejs.org/v2/guide/reactivity.html

for(var i = 0; i < getList.length; i++) {
    var newObject = Object.assign({}, getList[i]);
    this.$set(this.queuedItemList, i, newObject);
}

Another method might be to update the parent's item list :key - thus, rerendering it - everytime you add an item:

</div :key="computedKey">    
    <Item v-for="(item, index) in queuedItemList" :key="index" :componentData="item" :index="index" @remove="removeItem"></Item>
</div>

With

computed: {
    computedKey () {
        return this.queuedItemList.length
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

Will the key method work even if the length of the array doesn't change?
For some reason that doesn't work for me. Do I need to add a watcher somewhere?
The length needs to change, but this.$set should have done the trick :o
It did the trick, its just that my watcher on the other end was kind of broken. Thanks!
0

Turns out what I needed was a combination of setters and watchers. I used @alx.lzt's setters and a watcher on the component level and that solved everything

Comments

0

You can use several properties for reactivity check, $set to change the property in an object, $nextTick to assign the value.

If the both don't work you may try $forceUpdate()

Comments

0

i don't know the structure of "playcontrol"

<v-icon name="play" class="controlIcons" v-if ="playControl" />

I passed by something similar in past, when you update "playControl" value, you do just "playControl = newValue"? If you do, this can screw up the reactivity, try use Vue $set directive, like:

Vue.set(this.playControl, <value>);

https://v2.vuejs.org/v2/guide/migration.html#vm-set-changed

3 Comments

But playControl is just a boolean variable which is assigned like this.playControl = ['NotStarted', 'Stopped', 'Paused'].includes(this.componentData.State); during the creation. I'm not sure if that will work but I'll still give it a try.
I tried that, and I get "TypeError: right-hand side of 'in' should be an object, got boolean"
hmmmm, okey, once i need to force a component to refresh the code, Vue offers, "this.$forceUpdate()" try it after get the new list of items; br.vuejs.org/v2/api/index.html#vm-forceUpdate

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.