The v-list-group does not automatically expand sub-groups based on the path specified in the group prop

I have a navigation sidebar that includes nested v-list-groups. Based on the documentation, the "group" prop of v-list-group should expand based on the route namespace.

To see more information, visit: https://vuetifyjs.com/en/components/lists/

While this functionality works well with the top-level v-list-group, it opens up when the page is reloaded and the route matches the "group" prop.

However, this feature does not work for the sub-group v-list-groups. Upon reloading the page, I notice the subgroup closing, indicating that the group prop is working but something is causing it to close immediately after.

The code can be a bit complex, especially with variable naming. It involves rendering a list of navigation items where items without a subgroup defined appear as regular items, while those with a subgroup render as subgroups. This structure goes two levels deep.

This approach allows me to define the entire navigation bar in a single JSON file and import it into my project.

<template>
    <v-list dense nav>
        <template v-for="(sidebarItem, sidebarIndex) in sidebarItems">
            <v-list-item
                v-if="arrayIsEmptyOrUndefined(sidebarItem.subGroup)"
                :key="sidebarIndex"
                :to="sidebarItem.linkTo"
                nuxt
            >
                <v-list-item-action>
                    <v-icon>{{ sidebarItem.icon }}</v-icon>
                </v-list-item-action>
                <v-list-item-content>
                    <v-list-item-title v-text="sidebarItem.title" />
                </v-list-item-content>
            </v-list-item>

            <v-list-group
                v-if="
                    (!arrayIsEmptyOrUndefined(sidebarItem.subGroup) &&
                    typeof sidebarItem.subGroup !== 'undefined')
                "
                :key="sidebarIndex"
                :prepend-icon="sidebarItem.icon"
                :group="sidebarItem.linkTo"
            >
                <template v-slot:activator>
                    <v-list-item-content>
                        <v-list-item-title>{{ sidebarItem.title }}</v-list-item-title>
                    </v-list-item-content>
                </template>

                <v-list-item
                    v-if="arrayIsEmptyOrUndefined(sidebarItem.subGroup)"
                    :key="subGroupIndex"
                    :to="sidebarItem.linkTo"
                    nuxt
                >
                    <v-list-item-action>
                        <v-icon>{{ sidebarItem.icon }}</v-icon>
                    </v-list-item-action>
                    <v-list-item-content>
                        <v-list-item-title v-text="sidebarItem.title" />
                    </v-list-item-content>
                </v-list-item>

                <template v-for="(subGroupItem, subGroupIndex) in sidebarItem.subGroup">
                    <v-list-item
                        v-if="arrayIsEmptyOrUndefined(subGroupItem.subGroup)"
                        :key="subGroupIndex"
                        :to="subGroupItem.linkTo"
                        nuxt
                    >
                        <v-list-item-action>
                            <v-icon>{{ subGroupItem.icon }}</v-icon>
                        </v-list-item-action>
                        <v-list-item-content>
                            <v-list-item-title v-text="subGroupItem.title" />
                        </v-list-item-content>
                    </v-list-item>

                    <v-list-group
                        v-if="
                            (!arrayIsEmptyOrUndefined(subGroupItem.subGroup) &&
                            typeof subGroupItem.subGroup !== 'undefined')
                        "
                        :key="subGroupIndex"
                        sub-group
                        :group="subGroupItem.linkTo"
                    >
                        <template v-slot:activator>
                            <v-list-item-content>
                                <v-list-item-title>{{ subGroupItem.title }}</v-list-item-title>
                            </v-list-item-content>
                        </template>

                        <v-list-item
                            v-for="(subGroupSubGroupItem, subGroupSubGroupIndex) in subGroupItem.subGroup"
                            :key="subGroupSubGroupIndex"
                            :to="subGroupSubGroupItem.linkTo"
                            nuxt
                            exact
                        >
                            <v-list-item-content>
                                <v-list-item-title v-text="subGroupSubGroupItem.title" />
                            </v-list-item-content>
                            <v-list-item-action>
                                <v-icon>{{ subGroupSubGroupItem.icon }}</v-icon>
                            </v-list-item-action>
                        </v-list-item>
                    </v-list-group>
                </template>
            </v-list-group>
        </template>
    </v-list>
</template>

If both the group and subgroup match the route namespace, only the group expands. The Vuetify documentation website provides a functional example of this behavior. If you navigate to a sub-group and refresh the page, the sub-group remains open.

Answer №1

After what seemed like a simple task, I found myself struggling more than expected. To overcome this, I delved into the source code of the Vuetify docs site, focusing on key components like the main navigation drawer, the base-group component, the base-subgroup component, and the base-item component. These components were originally separated for easier management but are combined below:

<template>
  <v-navigation-drawer permanent>
    <v-toolbar color="indigo" dark>
      <v-app-bar-nav-icon></v-app-bar-nav-icon>  
      <v-toolbar-title>Main Menu</v-toolbar-title>
      <v-spacer></v-spacer>
      <v-btn icon>
        <v-icon>mdi-dots-vertical</v-icon>
      </v-btn>
    </v-toolbar>
    <v-list
      dense
      expand
      nav
    >
      <!-- ENTIRE list is wrapped in a template -->
      <template v-for="item in $router.options.routes">
        <!-- use v-if to determine if 2nd level nesting is needed -->
        <!-- if it's a menu item with no children -->
        <v-list-item
          v-if="!item.children"
          color="indigo"
          :key="item.name`"
          :to="item.path"
        >
          <v-list-item-icon>
            <v-icon>{{ `mdi-${item.meta.icon}` }}</v-icon>
          </v-list-item-icon>
          <v-list-item-title>{{ item.name }}</v-list-item-title>
        </v-list-item>
        <!-- else if it has children -->
        <v-list-group
          v-else
          :group="item.path"
          color="indigo"
        >
          <!-- this template is for the title of top-level items with children -->
          <template #activator>
            <v-list-item-content>
              <v-list-item-title>
                <v-icon>{{ `mdi-${item.meta.icon}` }}</v-icon>
                {{ item.name }}
              </v-list-item-title>
            </v-list-item-content>
          </template>
         [....] (The rest of the code has been abbreviated)
        </v-list-group>
      </template>
    </v-list>
  </v-navigation-drawer>
</template>

I realized that the menu was dynamically generated from Vue Router routes. Here is an example of what the router setup looks like:

const router = new VueRouter({
  routes: [
    {
      name: 'No Children (1 level)',
      path: '/no-children',
      meta: {
        icon: 'baby-carriage-off',
      },
    },
    {
      name: 'Attractions (2 levels)',
      path: '/attractions',
      meta: {
        icon: 'airballoon',
      },
      children: [
        { ... }
     ]
    },
    {
      name: 'Restaurants (3 levels)',
      path: '/restaurants',
      meta: {
        icon: 'silverware-fork-knife',
      },
      children: [
       { ... }
     ]
    },
  ]
})

Check out the complete working example on CodePen. It starts at the route

/restaurants/japanese/late-night-ramen
, and clicking any endpoint logs the application's routing path in the console. I hope this explanation clarifies things!

Answer №2

One method to achieve this is by utilizing 'to' as a routing solution, which will automatically recognize the current route.

      <v-list v-model:opened="open">
      <template v-for="(menu, j) in mainMenu">
        <v-list-group :value="menu.title" > ;
          <template v-slot:activator="{ props }"> ;
            <v-list-item
              v-bind="props"
              :key="menu.title + j"
              :value="menu.title + j"
            > ;
              <v-icon>{{ menu.icon }}</v-icon>
              {{ $t(menu.title) }}
            </v-list-item> ;
          </template> ;

          <v-list-item
             dense
             v-for="(item, i) in menu.subMenu"
             :key="item.title + j + i"
             :value="item.title + j + i"
             :title= & quot; item.title">
             :to= & quot; item.path"& >
          </v-list-item> ;
        </v-list-group> ;
       </template> ;
    </v-list> ;

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

The page refreshes automatically when the search icon is clicked, but the ajax method does not trigger the page reload

Whenever I click on the search-box <a>, the JavaScript is triggered but doesn't execute the ajax method filter_data_guide_specs(). Instead, the page automatically reloads and fails to read the JS code. HTML <div class="form-group"> < ...

Material UI - Array of Chips

I have been working on creating a ReactJS component that displays an array of chips with unique styling for each one. To achieve this, I created individual makeStyles classes for the chips. However, I encountered difficulties in dynamically changing the cl ...

After being deployed on Vercel, React is mistakenly redirecting to the incorrect file, although it functions properly when

I'm a beginner in JavaScript and I recently created a React project. Everything was working smoothly in local development until I deployed the project on Vercel. The issue is when a user clicks on the "about button," instead of showing 'about.htm ...

Script malfunctioning following an AJAX request

My page consists of a header where all my javascript is located. Within the body of the page, there is a link that triggers an ajax http request using vanilla JavaScript (not jQuery). This request retrieves a PHP form and injects it onto my page. The PHP ...

Optimal method for parsing URLs using ES6

There have been many remarkable inquiries regarding this topic, such as: how to parse a url. However, as time has gone by, the answers I come across are outdated. I am looking for a more modern and flexible method to parse URLs, without relying on regular ...

Unable to integrate a new third-party script into a Next.js application

In my attempt to integrate the following script, I have tried adding it first to _document.js, then to app.js, and finally to a specific page. <Script src="https://anywebsite.ai/chatbot/chatbot.js"></Script> <Script id=" ...

npm is facing difficulties while trying to install the scrypt package. It is prompting the requirement

When attempting to run a blockchain application, I encountered an error message that reads: npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! [email protected] install: node-gyp rebuild npm ERR! Exit status 1 npm E ...

Managing image src links in VueJS for both development and production modes

Struggling with loading images on my Vue.js app. Here's what I have: <img :src="imgSrc" /> It works fine in development mode: data() { return { imgSrc: require('../assets/MyLogo.png'), } } And it also works in production m ...

Error occurs in production environment in Vite 2 when the ref element is undefined while using the Composition API

While working with Vue3 and the composition API, I encountered an issue where the ref element remains undefined after building my project. I tried reproducing the problem and it seems like I might have used it incorrectly, but the reason behind this behav ...

Polymer custom components and Polymer motion recognition techniques

Looking to implement a listener event on a Polymer custom element using Polymer-gestures. Here is a snippet of my code: - my-custom-element.html <link rel="import" href="../polymer/polymer.html"> <polymer-element name="my-custom-element" attri ...

"Utilize Ajax to load PHP content and dynamically refresh a specific div

I have implemented an image uploading system, but now I want to incorporate a feature that allows users to rotate the uploaded images using Ajax. The challenge I'm facing is that if the session variable is lost during a full page update, I need to ens ...

Is there a method to instruct crawlers to overlook specific sections of a document?

I understand that there are various methods to control the access of crawlers/spiders to documents such as robots.txt, meta tags, link attributes, etc. However, in my particular case, I am looking to exclude only a specific portion of a document. This por ...

Is it possible to generate a triangular attachment below a div element?

My designer sent me a unique design and I'm wondering if it's possible to replicate using HTML, CSS, or JavaScript? https://i.stack.imgur.com/spB71.png I believe it can be done with CSS by creating a separate div positioned absolutely under the ...

What is the efficient way to toggle localStorage based on checkbox selection using jquery?

I am looking to efficiently manage localStorage using checkboxes. When a checkbox is checked, I want to add the corresponding value to localStorage, and remove it when unchecked. var selectedModes = new Array(); $('.play_mode').on('click& ...

Creating a unique Angular filter involves combining different techniques and functionalities to tailor

Hey there! I'm just diving into the world of Angular JS and I'm looking to filter any Twitter text that comes back containing a hashtag, and turn that word into a clickable link. For example: If the returned twitter text is "The quick brown #f ...

Checking parameters from two forms that are both associated with the same model in Rails

Recently, a new feature was added to the system - a phone and sim checker. Users are required to input their phone number into the first form. If the phone number is found in the database, a message indicating this is displayed. Otherwise, the form switche ...

Make your CSS and JS files smaller by using a PHP compression script in your WordPress child theme

  I am looking to implement a PHP script that will serve combined, pre-gzipped, and minified JS and CSS files. You can find the source code for this script here: https://code.google.com/p/compress/ I have a WAMP localhost with WordPress install ...

Is there a way to properly structure a JSON file for easy reading on localhost

I am having trouble with the formatting of my .json file while using backbone.js. I can't seem to pass in the url correctly. PlayersCollection = Backbone.Collection.extend({ model: Player, url: 'http://localhost/STEPS/data/players.js ...

Utilize PHP to transform JSON data into JavaScript

Hello, I am a newcomer to Stackoverflow and I need some assistance. My issue involves converting JSON with PHP to JavaScript. I am using PHP to fetch data from a database and create JSON, which I then want to convert for use in JavaScript as an object (obj ...

The JavaScript code is attempting to execute a PHP script, however, I am struggling to parse the JSON data returned for use in the

As a novice, I am in the process of creating a JavaScript function that calls a PHP script every second. The PHP script retrieves values from MySQL DB, encodes them into JSON, which is then decoded by JS to display them on an HTML page. I have two queries ...