Reputation: 1526
I have a menu and i want to know if there is a way to Add a Class by Children class Condition.
Example:
<ul :class="{ 'open' : ThereIsClassInChild }">
<li v-for="item in list" :class="{ 'active' : $route.name == item.routeName }">
<a>{{ item.name }}</a>
</li>
</ul>
I want to put the condition: the "open" class if there is "active" class inside li
@Edit
Navigation.vue
<template>
<router-link v-for="item in Menu" :to="{ name: item.KeyRouter }" tag="li" :class="{'active' : $route.name === item.KeyRouter }">
<a>{{item.Name}}</a>
<ul class="nav nav-second-level" v-if="item.SubMenu != null" :class="{ 'open' : isOpenComputed(item.SubMenu) }">
<router-link :to="{ name: SecondItem.KeyRouter }" tag="li" v-for="SecondItem in item.SubMenu" :class="{ 'active': $route.name === SecondItem.KeyRouter }">
<a>{{SecondItem.Name}}</a>
<ul class="nav nav-third-level" v-if="SecondItem.SubMenu != null" :class="{ 'open' : isOpenComputedTwo(SecondItem.SubMenu) }">
<router-link :to="{ name: ThirdItem.KeyRouter }" tag="li" v-for="ThirdItem in SecondItem.SubMenu" :class="{ 'active': $route.name === ThirdItem.KeyRouter }">
<a>{{ThirdItem.Name}}</a>
</router-link>
</ul>
</router-link>
</ul>
</router-link>
</template>
<script>
let once = true
let onceTwo = true
export default {
data: () => ({
Menu: []
}),
methods: {
isOpenComputed (Menu) {
if(Menu === true) {
console.log( "Menu Router 1 [ FORCED TRUE ]" )
return true
}
if(once){
console.log( "Menu Router 1 START" )
if(Menu.find( ( i ) => this.$route.name === i.KeyRouter ) != null){
console.log( "Menu Router 1 [ TRUE ]" )
once = false
return true
}
console.log( "Menu Router 1 [ FALSE ]" )
}
},
isOpenComputedTwo (Menu) {
if(onceTwo){
console.log( "Menu Router 2 [ START ]" )
if(Menu.find( ( i ) => this.$route.name === i.KeyRouter ) != null){
console.log( "Menu Router 2 [ TRUE ] " )
this.isOpenComputed(true)
onceTwo = false
return true
}
console.log( "Menu Router 2 [ FALSE ]" )
}
}
},
created() {
let Data = [{
"Name": "Menu 1",
"SubMenu": [{
"Name": "SubMenu 1-1",
"KeyRouter": "Produtos"
}]
},
{
"Name": "Menu 2",
"SubMenu": [{
"Name": "SubMenu 2-1",
"SubMenu": [{
"Name": "Third Page Test",
"KeyRouter": "PagTeste"
}, {
"Id": 5,
"Name": "Third Page Test 2",
"KeyRouter": "PagTesteTres"
}]
}]
}
]
this.Menu = Data;
}
}
</script>
My menu is generated this local object, the Routes and the class "Active" works well. I would like to put the condition to "open" class inside "ul" tag.
@FINAL EDIT - SOLUTION
I have create a second method to check if the third level page is open, check all subMenu of second level to open it.
*<template>
<router-link v-for="item in Menu" :to="{ name: item.KeyRouter }" tag="li" :class="{'active' : $route.name === item.KeyRouter }" :key="item.Id">
<a>{{item.Name}}</a>
<ul class="nav nav-second-level" v-if="item.SubMenu != null" :class="{ 'in' : isOpenComputedTwo(item.SubMenu) }">
<router-link :to="{ name: SecondItem.KeyRouter }" tag="li" v-for="SecondItem in item.SubMenu" :class="{ 'active': $route.name === SecondItem.KeyRouter }" :key="item.Id">
<a>{{SecondItem.Name}}</a>
<ul class="nav nav-third-level" v-if="SecondItem.SubMenu != null" :class="{ 'in' : isOpenComputed(SecondItem.SubMenu) }">
<router-link :to="{ name: ThirdItem.KeyRouter }" tag="li" v-for="ThirdItem in SecondItem.SubMenu" :class="{ 'active': $route.name === ThirdItem.KeyRouter }" :key="item.Id">
<a>{{ThirdItem.Name}}</a>
</router-link>
</ul>
</router-link>
</ul>
</router-link>
</template>
<script>
let once = true
let onceTwo = true
export default{
data: () => ({
Menu: []
)},
methods: {
isOpenComputed (Menu) {
if(once){
//console.log( "Menu Router 1 START" )
if(Menu.find( ( i ) => this.$route.name === i.KeyRouter ) != undefined){
console.log( "Menu Router 1 [ TRUE ]" )
once = false
return true
}
//console.log( "Menu Router 1 [ FALSE ]" )
} else return false
},
isOpenComputedTwo (Menu) {
if(onceTwo){
let a = false;
if(Menu.find( ( i ) => this.$route.name === i.KeyRouter ) != null){
onceTwo = false
return true
}
let getSubMenu = []
if(Menu.find( ( i ) => i.SubMenu != undefined )) {
Menu.find( ( i ) => {
getSubMenu = i.SubMenu
for(i = 0 ; getSubMenu.length > i ; i++){
if( getSubMenu[i].KeyRouter === this.$route.name ){
onceTwo = false
a = true;
}
}
} )
}
if(a){
return true
}
} else return false
},
created() {
let Data = [{
"Name": "Menu 1",
"SubMenu": [{
"Name": "Página 1",
"KeyRouter": "Produtos"
}]
},
{
"Name": "Menu 2",
"SubMenu": [{
"Name": "SubMenu 2",
"SubMenu": [{
"Name": "Página 2",
"KeyRouter": "PaginaDois"
}, {
"Name": "Pagina 22",
"KeyRouter": "PaginaDoisDois"
}]
},
{
"Name": "SubMenu 3",
"SubMenu": [{
"Name": "Página 3",
"KeyRouter": "PaginaTres"
}, {
"Name": "Pagina 3",
"KeyRouter": "PaginaTresTres"
}]
},
]
}
]
this.Menu = Data;
}
}
</script>*
Upvotes: 0
Views: 248
Reputation: 55644
I would simply make a computed property to check the list
data for an item with a matching route name:
computed: {
isOpen() {
return this.list.find((i) => this.$route.name === i.routeName)
}
}
And use that instead:
<li v-for="item in list">
<ul :class="{ 'open' : isOpen }">
<li :class=" { 'active' : $route.name == item.routeName } ">
{{ item.name }}
</li>
</ul>
</li>
The same logic applies to your second scenario, but you would need to use a method instead of a computed property to keep track of the open status of each sub-menu:
methods: {
isOpen(list) {
return list.find((i) => this.$route.name === i.KeyRouter);
}
}
Pass the sub-menu to the method like so:
<ul
class="nav nav-third-level"
v-if="item.SubMenu != null"
:class="{ 'open' : isOpen(SecondItem.SubMenu) }"
>
<router-link
:to="{ name: ThirdItem.KeyRouter }"
tag="li"
v-for="ThirdItem in SecondItem.SubMenu"
:class="{ 'active': $route.name === ThirdItem.KeyRouter }"
>
<a>{{ThirdItem.Name}}</a>
</router-link>
</ul>
Upvotes: 1