Reactive items inside list-item

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 :wink:

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