How to use v-model inside the v-for loop in order to access a current object


#1

I have a simple v-for loop that renders inputs with checked state depending on a boolean active property:

This is the model:

const inputs = [
   {
        year: '2012',
        active: false
   },
   {
        year: '2013',
        active: true
   }
]

And this is the template:

<li class="filter__item" v-for="{year, active} in inputs">
    <input class="filter__input" type="checkbox"
           :name="year"
           :id="year"
           :checked="active"
           v-model="active"
    >
</li>

I would expect v-model="active" to hold a reference to an object in a loop, but it doesn’t work this way. When checkboxes are selected/unselected then my model state remains unchanged. Am I doing something wrong or is it a Vue limitation? I also tried to replace v-model="active" with v-model="this", but it doesn’t work either.

I know that I could use $event.target.value together with v-for index in order to access inputs[index] and change the value… but it looks so jQuery-ish. I would feel very bad if I did it this way.

Is there any solution?


#2

It works fine if you don’t destructure the argument:

<ul>
  <li v-for="input in inputs">
    {{ input.year }}
    <input type="checkbox" v-model="input.active">
  </li>
</ul>

When you de-structure the argument you are just passing it two primitive values and vue isn’t able to pick up on those values (which are basically local to the loop function).


#3

Thanks. I’ve just found the solution on my own, I was about to write about it, but you were faster :slight_smile:

Additionaly, there was one more reason why it didn’t work. I’ve been using a computed property.

IMO it should be mentioned in the documentation, because this is not so obvious that destructuring can’t be used. It would be great if some message appeared in the js console too.


#4

The Problem is not so much with destructuring itself, and more with the fact that active is now a variable with a copy of the value from the object.

It happens in pure JavaScript as well:

arrray.forEach({active} => active = true)

The above does nothing, for the same reason.


#5

Ok, I see. I thought it’s a Vue-specific issue. I didn’t know that destructuring acts this way under the hood. I thought it’s just a syntactic-sugar.


#6

if inputs are stored in Vuex state, is there a way to bind those properties in strict mode?
How can I apply the computed setter & getter in a v-for loop?


#7

i know its an old topic but i found a couple of ways to use it without any issues

  • we can use the index from the v-for but it might produce some side effects, so 2xcheck b4 settling with it
<li v-for="(item,i) in items" :key="item.id">
    <input v-model="items[i].value">
</li>
  • or we can use a method to do the index lookup if the prev didnt work
<li v-for="item in items" :key="item.id">
    <input v-model="items[getIndex(items, item.id)].value">
</li>
getIndex(list, id) {
  return list.findIndex((e) => e.id == id)
},

#8

This helped me understand it so much better! Thanks!