With Vue.js, I'm showing the list of items with a checkbox. Clicking on Checkbox will move the item down with strike-through. The issue is, when I click on the checkbox, the wrong checkbox is checked.
For eg, when I click on Apple checkbox, orange checkbox is checked.
Fiddle: /
Here's my code,
var myApp = new Vue({
el: '#myApp',
data: {
lists: [
{title: 'Apple', isChecked: false},
{title: 'Orange', isChecked: false},
{title: 'Grapes', isChecked: false}
]
},
puted: {
filterLists: function(){
return _.orderBy(this.lists, ['isChecked', false]);
}
},
methods: {
pleteTask: function(e, i){
e.preventDefault();
this.lists[i].isChecked = !this.lists[i].isChecked;
}
}
})
pleted{
text-decoration: line-through;
color: red;
}
<script src=""></script>
<script src=".17.4/lodash.min.js"></script>
<div id="myApp">
<ul>
<li v-for="(list, index) in filterLists">
<input type="checkbox" v-bind:id="'todo-' + index" v-on:change="pleteTask($event, index)" />
<span class="title" v-bind:class="{pleted: list.isChecked}">{{list.title}}</span>
</li>
</ul>
</div>
With Vue.js, I'm showing the list of items with a checkbox. Clicking on Checkbox will move the item down with strike-through. The issue is, when I click on the checkbox, the wrong checkbox is checked.
For eg, when I click on Apple checkbox, orange checkbox is checked.
Fiddle: https://jsfiddle/d6encxe1/
Here's my code,
var myApp = new Vue({
el: '#myApp',
data: {
lists: [
{title: 'Apple', isChecked: false},
{title: 'Orange', isChecked: false},
{title: 'Grapes', isChecked: false}
]
},
puted: {
filterLists: function(){
return _.orderBy(this.lists, ['isChecked', false]);
}
},
methods: {
pleteTask: function(e, i){
e.preventDefault();
this.lists[i].isChecked = !this.lists[i].isChecked;
}
}
})
.pleted{
text-decoration: line-through;
color: red;
}
<script src="https://unpkg./vue"></script>
<script src="https://cdn.jsdelivr/lodash/4.17.4/lodash.min.js"></script>
<div id="myApp">
<ul>
<li v-for="(list, index) in filterLists">
<input type="checkbox" v-bind:id="'todo-' + index" v-on:change="pleteTask($event, index)" />
<span class="title" v-bind:class="{pleted: list.isChecked}">{{list.title}}</span>
</li>
</ul>
</div>
Share
Improve this question
edited Jun 16, 2017 at 10:42
Muthu Kumaran
asked Jun 16, 2017 at 8:56
Muthu KumaranMuthu Kumaran
17.9k5 gold badges50 silver badges72 bronze badges
1
-
try moving
v-for
toli
and put akey
attribute onli
that is unique (can betitle
in your case) – riyaz-ali Commented Jun 16, 2017 at 9:11
3 Answers
Reset to default 4Use a key. A key uniquely identifies an element in Vue. If you do not use a key, Vue will try to re-use existing elements for performance.
To give Vue a hint so that it can track each node’s identity, and thus reuse and reorder existing elements, you need to provide a unique key attribute for each item. An ideal value for key would be the unique id of each item.
You should always use a key when rendering list. Here I'm using the title of your list items, but ideally you should generate a unique key.
<li v-for="(list, index) in filterLists" :key="list.title">
Also you do not need to pass indexes around. Just pass the item itself.
v-on:change="pleteTask(list)"
And in pleteTask, check it off.
pleteTask: function(task){
task.isChecked = !task.isChecked
}
Finally, iterate over your li
element and not your ul
element.
Updated fiddle.
The index screws things up, you can fix it by binding the checked state
<input type="checkbox" v-bind:checked="list.isChecked" v-bind:id="'todo-' + index" v-on:change="pleteTask($event, index)" />
And changing the plete task to just pass the item in:
<input type="checkbox" v-bind:id="'todo-' + index" v-on:change="pleteTask(list)" v-bind:checked="list.isChecked" />
See fiddle:
https://jsfiddle/d6encxe1/3/
You should remove the 'id' or use something other than the index of the loop because when you re-order the index doesn't change.
You probably want to put v-for
in <li>
instead of <ul>
, or your will get several <ul>
elements.
And you didn't provide a key
. You should provide a unique key for the items. For example, if the title
is unique, you can use it as the key
, or you may need to add another attribute like id
.
Besides, you can pass the entire list item to the method instead of just the index, because the indexes are changeable in your case:
v-on:change="pleteTask($event, list)"
Working example here: https://jsfiddle/0r2yb0z6/1/