I am trying to create a menu on Vue 3 with categories and subcategories. The goal is that when I click on a category, the subcategories specific to that category will appear below and be removed when I click again. The problem is that I can't get the function to be specific to each category. Whenever I click on a category, the subcategories of all categories are displayed.
I reproduced my code in a simpler example.
JS :
const menu = [
{
label: "Category 1",
key: "category_1",
subcategories: [
{
label: "1 - Subcategory 1",
key: "1_subcategory_1",
},
{
label: "1 - Subcategory 2",
key: "1_subcategory_2",
},
],
},
{
label: "Category 2",
key: "category_2",
children: [
{
label: "2 - Subcategory 1",
key: "2_subcategory_1",
},
],
},
];
const isDisplay = ref(false);
const showSubcategories = () => {
isDisplay.value = !isDisplay.value
}
VUE :
<template>
<div v-for="category in menu" :key="category.key">
<div @click="showSubcategories()">
<span> {{ category.label }}</span>
</div>
<div v-if="isDisplay">
<div
v-for="subcategory in category.subcategories"
:key="subcategory.key"
>
{{ subcategory.label }}
</div>
</div>
</div>
</template>
I suspect that I have to add an index (like showSubcategories(category.key)
)or pass one or more parameters to my function but despite my attempts, I can't solve the problem. Thanks in advance.
You have a few options to do this. You can add additional property to each category to track if it is open or not, or you can have a separate variable to store IDs of open categories.
Here is example with a separate variable to store IDs of open categories:
const menu = [
{
label: "Category 1",
key: "category_1",
subcategories: [
{
label: "1 - Subcategory 1",
key: "1_subcategory_1",
},
{
label: "1 - Subcategory 2",
key: "1_subcategory_2",
},
],
},
{
label: "Category 2",
key: "category_2",
subcategories: [
{
label: "2 - Subcategory 1",
key: "2_subcategory_1",
},
],
},
];
const openCategories = ref([]);
const toggleSubcategories = (categoryId) => {
if(openCategories.value.includes(categoryId)) {
openCategories.value.splice(openCategories.value.indexOf(categoryId), 1);
} else {
openCategories.value.push(categoryId);
}
}
<template>
<div v-for="category in menu" :key="category.key">
<div @click="toggleSubcategories(category.key)">
<span> {{ category.label }}</span>
</div>
<div v-if="openCategories.includes(category.key)">
<div
v-for="subcategory in category.subcategories"
:key="subcategory.key"
>
{{ subcategory.label }}
</div>
</div>
</div>
</template>