"Exploring the Power of VueJS Classes and Conditions

Is it possible to add a Class based on a Child's Class Condition in the menu?

For example:

<ul :class="{ 'open' : ThereIsClassInChild }">
    <li v-for="item in list" :class="{ 'active' : $route.name == item.routeName }">
          <a>{{ item.name }}</a>
    </li>
</ul>

I am trying to add the "open" class if any child li has the "active" class.

@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": "Products"
                }]
            },
            {
                "Name": "Menu 2",
                "SubMenu": [{
                    "Name": "Submenu 2-1",
                    "SubMenu": [{
                        "Name": "Third Page Test",
                        "KeyRouter": "TestPage"
                    }, {

                        "Id": 5,
                        "Name": "Third Page Test 2",
                        "KeyRouter": "TestPageThree"
                    }]
                }]
            }
        ]
        this.Menu = Data;
    }
}
</script>

The navigation menu is generated from this local object, and the Routes and the "Active" class work correctly. I would like to set the condition for the "open" class within the "ul" tag.

@FINAL EDIT - SOLUTION

I have created a second method to check if the third level page is open by examining all submenus of the second level.

    *<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>*

Answer №1

To simplify the process, a computed property can be created to check the data in the list for an item with a matching route name:

computed: {
  isItemOpen() {
    return this.list.find((item) => this.$route.name === item.routeName)
  }
}

This computed property can then be used as follows:

<li v-for="item in list">
   <ul :class="{ 'open' : isItemOpen }">
      <li :class=" { 'active' : $route.name == item.routeName } "> 
           {{ item.name }}
      </li>
   </ul>
</li>

A similar approach can be taken for the second scenario, however, a method should be used instead of a computed property to manage the open status of each sub-menu:

methods: {
  isSubMenuOpen(list) {
    return list.find((subItem) => this.$route.name === subItem.KeyRouter);
  }
}

You can pass the sub-menu to the method like this:

<ul 
  class="nav nav-third-level" 
  v-if="item.SubMenu != null" 
  :class="{ 'open' : isSubMenuOpen(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>

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

Is there a way to shade the entire webpage background in HTML?

Instead of affecting other DOM classes, I tried using another div but it doesn't darken the whole page. This means I have to manually modify each DOM class. Is there a way to overlay the entire document with a semi-transparent gray plane? ...

Having trouble with spawning child processes asynchronously in JavaScript

I'm trying to figure out how to format this code so that when a user clicks a button, new input fields and redirect buttons are asynchronously inserted into the unordered list. Everything was working fine until I added the redirect button insertion fu ...

Retrieve an item from an array based on the unique ID value of the button that was clicked using

I am working with a phones array that is populated with JSON data: var phones = [ { "age": 0, "id": "motorola-xoom-with-wi-fi", "imageUrl": "img/phones/motorola-xoom-w ...

The error handler function is missing in Zepto's $.post method

When I was using Zepto instead of jQuery, I noticed that while the $.ajax method has an error handler, other methods like $.post and $.get do not. Do you know why this is the case? Function Signature $.post(url, [data], function(data, status, xhr){ ... }, ...

What is the method to access 'let' variables in the console of a developer tool?

When you open the Chrome devtool and enter the code snippet below: // The iife is irrelevant let r = (() => { return 2; })(); and then evaluate r, the output will be: r 2 Surprisingly, both window.r and globalThis.r return undefined. Although let is ...

The 'admin' attribute is not found in the 'Object' data type

I have been facing this issue for quite some time now. The backend API response is indicating that a certain property does not exist, even though it clearly does. My Angular application suddenly started showing 18 errors today, and I am at a loss on how ...

Discover the position within a two-dimensional array

Suppose I have an array that contains objects, and each object has its own id property. In this case, I can find the index by writing: data.findIndex(x=>x.id === newData.id); Now, if data is an array of arrays of objects, how can I efficiently get two ...

Express server encounters a 404 error while processing a POST request

Recently, I encountered an issue while trying to post data to my express server using a function that is triggered by clicking a button. Here's the code snippet of the function: const fetchData = async () => { const response = await fetch(&apos ...

What is the best way to tally the frequency of words in a collection of URLs using JavaScript?

I have a JSON object in WordPress that contains a list of URLs. I would like to determine the frequency of occurrence of the second part of each URL. Currently, the code snippet below is able to extract the remaining part of the URL after the prefix https ...

How to efficiently create a unique object on MongoDB during the first instance

In the project I'm working on, there is a feature where a user can create a safe by visiting /mysafe. However, I want this safe to be created only once when they first visit the page. Subsequent visits should redirect them to /mysafe/theidofit. Have ...

Is it possible to eliminate the arrows from an input type while restricting the change to a specific component?

Is there a way to remove the arrows from my input field while still applying it only to the text fields within this component? <v-text-field class="inputPrice" type="number" v-model="$data._value" @change="send ...

Can one showcase a php content using an ajax event?

I’m having trouble asking the right question because I’m not sure what I’m doing. I have a form that includes a default PHP script that creates three different lines: <form method="GET" name="NewDeliveryNote" action="ItemPosts_INSERT.php"> < ...

What is the reason behind the undefined value of "this" in this particular class method?

I have scoured the depths of the internet in search of a solution, but I am still grappling with an issue related to a JS class I am developing for a Micro Service (still learning as I go). When attempting to call a method within a class on an instantiate ...

Determine the status of a checkbox in Protractor with JavaScript: Checked or Unchecked?

I'm currently facing a challenge while writing an end-to-end Protractor test. I need to verify whether a checkbox is enabled or not, but it doesn't have a 'checked' property. Is there a way in JavaScript to iterate through a list, check ...

Issue encountered: Inoperable binding when employing ko.mapping with two distinct models

I've been struggling to implement a drop-down select in conjunction with a table on a page using knockout bindings. The issue arises when I try to use the mapping options in the knockout binding plugin – either the drop-down or the table behaves inc ...

Tips for quietly printing a PDF document in reactjs?

const pdfURL = "anotherurl.com/document.pdf"; const handleDirectPrint = (e: React.FormEvent) => { e.preventDefault(); const newWin: Window | null = window.open(pdfURL); if (newWin) { newWin.onload = () => ...

Tips for designing a search bar using Angular

search : ____________ I am interested in designing a search bar functionality that automatically triggers when the user inputs 8 or more characters. The input text will be stored in a variable, the search bar will be reset, and the backend API will be che ...

A guide to verifying a user's age using JavaScript by collecting information from 3 separate input fields

On page load, only the year input is required for users to fill in. The user can enter their birth year first without providing the month and day. Currently, I have a function that checks if a person is over 16 years old by comparing their birth year with ...

Verify if a <select> element exists inside the main div

Is there a way for me to check if a <select> element is present within the parent div and display certain content based on its existence? Appreciate any assistance! ...

What steps can I take to improve this code and prevent the error "Property 'patient' does not exist on type 'Request<ParamsDictionary>'" from occurring?

I'm having some issues with my code. I am attempting to use passport authenticate in order to save patient information that is specific to the token generated for each individual. router.get("/current", passport.authenticate("jwt", { session: false }) ...