Title: VueJS How to show/hide closest hidden element in list of items
Tags: javascript;vue.js;vuejs2
Question: How can I show/hide the closest div by clicking a button in vue?
lets say I have a list of items, each with some hidden details
<ul&gt;
<li v-for="item in items" :key="item.id"&gt;
<div&gt;
<p&gt;{{item.text}}</p&gt;
<button @click="showDetails(item)"&gt;Show details</div&gt;
<div class="details" :class="isVisible ? activeClass : 'hidden'"&gt;Some hidden details</div&gt;
</div&gt;
</li&gt;
</ul&gt;
Then I do
data() {
return {
items: [ // a bunch of item objects here]
isVisible: false,
activeClass: 'is-visible'
methods: {
showDetails(item) {
this.isVisible = item;
Right now, when I click on on of the "showDetails" buttons, all divs with class .details opens and get the .is-visible-class, but I just want the closest div to the item to be displayed. For some reason I think this is pretty simple, but I can't make it work.
How can I achieve that?
Comment: Hmm, this doesn't work...

Comment: change `@click="item.isVisible = true"` then `:class="item.isVisible ? item.activeClass : 'hidden'"`

Comment: I can see what you done.. your comment on `items:` makes it look like `isVisible` is part of  `items:`.. which its not, but it should be.. each item should have a *show* state which you toggle, or use a single var which holds the index of the shown item, then do it on that, abit more complicated.


Here is another answer: Just store "isVisible" variable inside the "item"
<ul&gt;
<li v-for="item in items" :key="item.id"&gt;
<div&gt;
<p&gt;{{item.text}}</p&gt;
<button @click="showDetails(item)"&gt;Show details</div&gt;
<div class="details" :class="item.isVisible ? activeClass : 'hidden'"&gt;Some hidden details</div&gt;
</div&gt;
</li&gt;
</ul&gt;
data() {
return {
items: [ // a bunch of item objects here]
isVisible: false,
activeClass: 'is-visible'
methods: {
showDetails(item) {
item.isVisible = !item.isVisible;
this.$forceUpdate();

Here is another answer: It would be clearer to create a new component for list item which would contain all logic itself. Something like:
// ListItem.vue
<template&gt;
<div&gt;
<p&gt;{{text}}</p&gt;
<button @click="toggleVisibility"&gt;Show details</button&gt;
<div class="details" v-show="isVisible"&gt;Some hidden details</div&gt;
</div&gt;
</template&gt;
<script&gt;
props: {
text: String
data() {
return {
isVisible: false
methods: {
toggleVisibility() {
this.isVisible = !this.isVisible
</script&gt;
and in your parent component:
<ul&gt;
<li v-for="item in items" :text="item.text" :key="item.id" is="list-item" /&gt;</li&gt;
</ul&gt;
data() {
return {
items: [ // a bunch of item objects here]

Here is another answer: try this
<template&gt;
<ul&gt;
<li v-for="(item, i) in items" :key="item.id"&gt;
<div&gt;
<p&gt;{{item.text}}</p&gt;
<button @click="showDetails(i)"&gt;Show details</button&gt;
<div class="details" :class="i == active ? activeClass : 'hidden'"&gt;Some hidden details</div&gt;
</div&gt;
</li&gt;
</ul&gt;
</template&gt;
<script&gt;
export default {
data() {
return {
items: [],
activeClass: 'is-visible',
active: null
};
methods: {
showDetails(i) {
this.active = i;
</script&gt;

{'source': 'StackExchangeDataset', 'subset': 'stackoverflow.com', 'metadata': {'AnswerCount': 3, 'CommentCount': 3, 'ContentLicense': 'CC BY-SA 4.0', 'CreationDate': '2019:00:10/30/19', 'FavoriteCount': None, 'PostTypeId': 1, 'Tags': '<javascript><vue.js><vuejs2>', 'Title': 'VueJS How to show/hide closest hidden element in list of items', 'ViewCount': 4494, 'id': 58621835, 'user_AboutMe': None, 'user_AccountId': 4910077.0, 'user_DisplayName': 'ST80', 'user_Reputation': 3297.0, 'user_Views': 479.0, 'user_id': 3955607.0}}