I'm making a list of items with v-for loop. Inside each item of the loop there is button with click event method that showing description text.
When i click on the button, it should toggle only inside it's own item, but it affecting all elements in v-for list.
So, how to make a toggle method that will affect only it's own item?
<template>
<div>
<div v-for="item in items" :class="{ activeclass: isActive }">
<div class="item-text">
{{item.text}}
</div>
<button @click="toggle()">show</button>
<div v-show="isActive" class="item-desc">
{{item.desc}}
</div>
</div>
</div>
</template>
<script>
export default {
data () {
return {
items: [
{
text: 'Foo',
desc: 'The Array.from() method creates a new Array instance from an array-like or iterable object.',
},
{
text: 'Bar',
desc: 'The Array.from() method creates a new Array instance from an array-like or iterable object.',
}
],
isActive: false
}
},
methods: {
toggle: function () {
this.isActive = !this.isActive;
}
},
}
</script>
As @Nora said you can (and probably should) create a separate component for each list item, so you would have a component that accepts an item
as a prop, then each component can have it's own isActive
flag, which keeps the markup nice and clean:
Component:
Vue.component('toggle-list-item', {
template: '#list-item',
props: ['item'],
methods: {
toggle() {
this.isActive = !this.isActive;
}
},
data() {
return {
isActive: false
}
},
})
Markup
Now you can simply place the component inside your v-for
:
<div id="app">
<div v-for="item in items">
<toggle-list-item :item="item"></toggle-list-item>
</div>
</div>
Here's the JSFiddle: https://jsfiddle.net/w10qx0dv/
You can add a property on each item in your list if description should be shown:
<template>
<ul>
<li v-for="item in items" :class="{ activeclass: item.isActive }">
<div class="item-text">
{{ item.text }}
</div>
<button @click="toggle(item)">show</button>
<div v-show="item.isActive" class="item-desc">
{{ item.desc }}
</div>
</li>
</ul>
</template>
<script>
export default {
data () {
return {
items: [
{
isActive: false,
text: 'Foo',
desc: 'The Array.from() method creates a new Array instance from an array-like or iterable object.',
},
{
isActive: false,
text: 'Bar',
desc: 'The Array.from() method creates a new Array instance from an array-like or iterable object.',
}
],
}
},
methods: {
toggle: function (item) {
item.isActive = !item.isActive;
}
},
}
</script>
Alternatively, you can extract the li
into a separate component.