[Vuejs]-VueJS – How to use v-model in the right way when using child components

2👍

https://v2.vuejs.org/v2/guide/reactivity.html#For-Arrays

Vue cannot detect the following changes to an array:

  1. When you directly set an item with the index, e.g. vm.items[indexOfItem] = newValue
  2. When you modify the length of the array, e.g. vm.items.length = newLength

The problem is that you are doing v-model="checkboxes[child.id].value".
V-model is really just a fancy way of doing:

 <input type="checkbox" :value="checkboxes[child.id].value" @input="checkboxes[child.id].value = $event"

The @input part in your v-model is what Vue cannot detect. I think for this issue if you need the checkboxes and items separated, and you don’t want to rewrite a lot, you have to ditch v-model and use value and @input separately:

 <input type="checkbox" :value="checkboxes[child.id].value" @input="toggleCheckbox(child.id)"
methods: {
  toggleCheckbox(index) {
   this.checkboxes.splice(index, 1, !this.checkboxes[index].value)
  }
}

this being if I understood you correctly that child.id corelates to index in checkboxes array.

HOWEVER

I see that you are in fact mutating your props, which in Vue is a bad practice.
You should use the prop/emit workflow. This means that the parent should always be responsible for data changes.

So the best way would be to change the toggleCheckbox funxtion above to emit the change up and then let the parent mutate the checkboxes array. Once the parent does this, the child will automatically change too.

1👍

As already answered by Sølve Tornøe reactivity is a thing to take care about in Vue, especially for Arrays as seen here. That’s also the reason why your updated Array doesn’t work.

However, the solution for your issue is pretty simple and doesn’t require a lot. Let’s take a closer look into your checkbox.

<input type="checkbox" v-model="checkboxes[child.id].value" :value="1" />

While this looks fine initially, your v-model binding won’t update your arrays value due to above mentioned reactivity issues. Instead, add an additional @update binding as well as an index for your loop.

<input type="checkbox" v-model="checkboxes[child.id].value" :value="1" @input="updateCheckbox(i, child.id)" />

Your method could then look like this

updateCheckbox(i, id) {
  this.$set(item.childrens[i], id, 'some value here');
}
👤Aer0

Leave a comment