Switching the parent to child component value in Vue.js to show or hide elements using v-show within a v-for loop

I'm attempting to display a list of items in a v-for and toggle their visibility individually.

Initially, I had all the code in one component which caused every element in the loop to open when the button was clicked:

<template>
  <div v-for='item in items'>
    <button @click="isExpanded = !isExpanded">Toggle specific element</button>
    <ul v-show="isExpanded">
      <li v-for='subitem in item.subitems'>Sub items</li>
    </ul>
  </div>
</template>

<script>
  export default {
    data() {
      return: {
        isExpanded: false
      };
    },
  };
</script>

I wanted only one item to expand at a time when clicked.

Eventually, I decided to move my ul list to a separate component.

<template>
  <div v-for='item in items'>
    <button @click="??">Toggle specific element</button>
    <MyListComponent :items="item.subitems"/>
  </div>
</template>

  <script>
  import MyListComponent from '…'
   export default {
     data() {
        return: {
            isExpanded: false
        }
     },

     components: { 
       MyListComponent 
     }
   }
  </script>

MyListComponent :

<template>
<ul v-show="isExpanded">
  <li v-for='item in items'>Sub items</li>
</ul>
</template>

<script>
export default {
     data() {
        return: {
            isExpanded: false
        }
     },

     props: ['items'],

     methods: {
        toggle() {
          this.isExpanded = !isExpanded;
        }
     }
</script>

However, I am unable to make the click event on the parent button change the "isExpanded" value in the child component.

Could you please provide guidance on how to achieve this?

Answer №1

In order to handle the display of items, Delena Malan suggests using props. It is important to have a separate "isExpanded" variable for each item that is being displayed. One way to achieve this is by storing it within the items array so that each item can have its own boolean value for isExpanded.

<div v-for="(item, index) of items" :key="index">
  <button @click="item.isExpanded = !item.isExpanded">Toggle specific element</button>
  <Item :subItems="item.subItems" :isExpanded="item.isExpanded"/>
</div>

If you're curious about how I implemented this approach, feel free to check out my version on this Codesandbox

Answer №2

Implement a new approach by removing all isExpanded functionality in child lists and handling it in the parent component before passing it down to the child.

<template>
  <div v-for='item in items'>
    <button @click="ToggleIsExpanded">Toggle specific element</button>
    <MyListComponent :items="item.subitems" :isExpanded="isExpanded"/>
  </div>
</template>

  <script>
  import MyListComponent from '…'
   export default {
     data() {
        return: {
            isExpanded: false
        }
     },

     components: { MyListComponent },
     methods: {
       ToggleIsExpanded: function() {
         this.isExpanded = !this.isExpanded
       }
     }
   }
  </script>

MyListComponent :

<template>
<ul v-show="isExpanded">
  <li v-for='item in items'>Sub items</li>
</ul>
</template>

<script>
export default {
     props: ['items', 'isExpanded']
</script>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

On smaller screens, the top placement of right sidebar links is necessary

Our website layout is organized into 3 main sections: the top part contains the main menu, followed by the main content and a sidebar specific to each page. The main content and sidebar are structured using bootstrap col-* classes. On small screens, I en ...

Creating a dynamic template in AngularJS directive

I am curious about how to create a dynamic template directive. Here's the challenge - when I am on the main page or main categories such as page1 or page2, my template should include all the divs. However, when I am on a submenu like subpage1 or subp ...

Steps to open and configure a Mobile-Angular modal from another controller

Is it possible to use a modal in Angular JS for mobile devices without compromising the layout? I'm having trouble setting up the controller for my modal inside my main controller and passing parameters. Should I consider using ui-bootstrap for this p ...

The console is failing to display the value associated with the key

In this snippet of JSON code, the key "pants" is nested under the "children" key for MALE when gender is selected as male. However, if the selected gender is female, then "pants" becomes a children key of FEMALE. var data = { "gender": "male", "myFi ...

Creating a universal method in Vue.js 2 and passing parameters

I have a scenario where I need to update the title and description in a component's mounted() lifecycle hook. However, I am looking to create a global function that can be reused for this purpose. Is there a way to achieve this efficiently? window.d ...

What strategies can be employed to streamline the code provided?

Can someone help simplify this JavaScript code for me? I would really appreciate it. Thank you! $(function() { $("#show1").click(function() { $("#showmore1").toggle(); }) $("#show2").click(function() { $("#showmore2").toggle(); ...

Is it possible to remove Sprites from a three.js scene?

Currently facing an issue where I am trying to update axis labels on a 3D plot by removing the old labels (implemented as sprites) before adding new ones. Unfortunately, I am experiencing difficulties. The previous labels seem to persist in the scene even ...

Autofill functions may not be compatible with input fields generated using JavaScript

Having trouble with browsers not using autocomplete in login overlays generated with JavaScript? It can be really annoying. Any suggestions on how to fix this issue? Should I create a hidden form within the original HTML and then move it into the overlay? ...

Obtain the AngularJS service using Vanilla JavaScript

Trying to access the AngularJS service from plain JavaScript. Utilizing the following syntax: angular.injector(['ng', 'error-handling']).get("messagingService").GetName(); It works fine when the messagingservice has no dependencies. H ...

When the add button is clicked, I would like to implement a feature where a checkbox is added

When the user clicks on the link "출력하기", I want the web page to add a checkbox to all images. I wrote this code, but it's not working. Can anyone help me? This is my JS: $(document).ready(function(){ $("#print").on('click', fu ...

Storing data from an API response into the localStorage using Vue.js upon clicking

My objective is to save specific data in the browser's localStorage upon clicking a link. However, the output I receive is either undefined or completely empty. <li v-for="(category, index) in categories" :key="index"> ...

Setting default values for JSON objects by analyzing the data of other objects within the array

I've been grappling with this issue for about 6 days now, so please bear with me if my explanation is a bit convoluted. I'm using NVD3 to showcase graphs based on data retrieved from BigQuery. While the data and graph setup are correct, the probl ...

Incorporating React into an already existing webpage and accessing URL parameters within a .js file

Following the official guidelines: To include React in a website, visit https://reactjs.org/docs/add-react-to-a-website.html I have created a file named test.html with the following content: <!DOCTYPE html> <html> <head> < ...

Increase the spacing between the column label and the x-axis label in a c3 chart

Take a look at the chart below, I'm attempting to create some additional spacing between the column labels and the x-axis label. https://i.sstatic.net/R7zqN.png I experimented with adding this CSS style: text.c3-axis-x-label { margin-top: 10 ...

Using API call responses to initiate a render in React

As a newcomer to React, I'm facing an issue with passing the results of my API call to another component file in order to trigger a render. Can anyone provide a straightforward explanation of what steps I need to take? In my code, I make a call to th ...

The child route's vue-router named view is failing to function accurately

The nested route with a named router view is not loading correctly. When clicking the links in the navigation drawer, the corresponding content should be displayed in the v-content component. I have implemented this using named router views. Below are the ...

Why does the width of my image appear differently on an iPhone compared to other devices?

I recently encountered an issue with the responsiveness of an image on my website. While it displayed correctly on Android and desktop devices, the image appeared distorted on iPhones as if the CSS width attribute was not applied properly. This problem spe ...

Is there a way to remove a portion of a string?

Looking to remove a section of a string using JavaScript? I attempted var sentence = "C:\mnt\c\User\Foo\Bar"; var updatedSentence = sentence.replace("mnt\c", ""); But the result was not as expected ...

The MUI select box stays fixed in its position relative to both the height and width of the viewport while scrolling

Whenever I click on the MUI select, the dropdown box stays fixed in the viewport both horizontally and vertically as I scroll. Ideally, it should move along with the select. Any ideas on how to fix this issue? I attempted adjusting the positioning of the ...