What’s the proper way to add reactivity to controls inside list-items?
Here’s an example (it’s a little pointless, but shows what I mean):
<f7-list>
<f7-list-item v-for="(itm, idx) in items" :key="idx">
<f7-checkbox @change="itm.visible != itm.visible" :checked="itm.visible"></f7-checkbox>
<f7-icon :f7="itm.visible ? 'eye' : 'eyeoff'"></f7-icon>
<f7-checkbox @change="itm.visible != itm.visible" :checked="itm.visible"></f7-checkbox>
</f7-list-item>
</f7-list>
If I click any of the items, the others should swap their state accordingly.
Do I need to send an event to the list to force a redraw, or is there a more ‘reactive’ way to do that?
This is the correct way of doing it, so on inputs you just have a combination of @input
/@change
handlers + value
/checked
props.
Also it depends on context, but on checkboxes i also do like this:
... @change="itm.visible = $event.target.checked"
Thanks - but that (unfortunately) doesn’t seem to work for me in slots (or other items inside list-item).
I think I will $emit/catch the change to get that working
Can you show some more real example where it causes issue? Maybe error is somewhere else
This is basically a ‘real’ example (I just use other controls).
I can easily fix it using this.$forceUpdate()
, which works fine.
But I’ll clean up the list and post a fiddle or some code here…
1 Like
OK - it boils down to this:
- if I pass the layers as props to a template (or via the
this.$root.leftPanelProps
(we wer discussing recently elsewhere) I’m loosing the ability to use the ‘reactive’ refresh in the slots (which I can fix by the forceUpdate
one-liner. (not nice, but gets the job done)
- if I put everything in a fiddle (without external) template it works out of the box
So it can very well be I do something (quite) wrong -> but as long as it works I’m okay with that 
If I find some time I will try to reproduce it in a fiddle…
I can suggest that you have a pretty common Vue’s reactivity error, when you assign some component’s data that wasn’t declared on its creation. This is pretty useless and abstract example:
<template>
<div>
<p>{{foo}}</p>
<p v-if="bar">{{bar}}</p>
</div>
</template>
<script>
export default {
data() {
return {
foo: 'Foo',
};
},
mounted() {
setTimeout(() => {
this.bar = 'Bar';
}, 1000);
},
}
</script>
In this case template won’t be rerendered when we add this.bar = 'Bar'
because we haven’t decalted bar
in original data()
. To make it work we need to set it here correctly with this.$set(this, 'bar', 'Bar)
.
So i suggest you may have similar issue, so check that all reactive data you relies on is in component’s data()
or you set it with $set
instead. It is also the case for nested objects and properties.
I recommend you to read this doc as well https://vuejs.org/v2/guide/reactivity.html