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.

https://i.sstatic.net/1lNPd.png

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

I encountered login issues when trying to access dist/index.html in my Angular 8 application, but I found a workaround by utilizing the proxy.conf.json file, which

I have been trying to login through the index.html page in the angular 8 dist folder, but I keep encountering an error with the login API URL. Despite spending two days on this issue, I have not been able to find a solution. If anyone has any suggestions o ...

Input form with multiple fields. Automatically display or hide labels based on whether each field is populated or empty

I am attempting to create a form where the placeholders move to the top of the input when it is focused or filled. However, I have encountered an issue with having multiple inputs on the same page. Currently, my JavaScript code affects all inputs on the pa ...

Is it possible to expand the CORS permissions to the routers directly from the app?

I have a couple of questions: Is it possible to just use cors() once in my server.js instead of having to call and use it in every router file? Can I simply require express once in my server.js without having to call it in all my router files? Currently, ...

What could be causing my Vue component to not refresh?

Can anyone help me figure out why this component isn't re-rendering after changing the value? I'm attempting to create a dynamic filter similar to Amazon using only checkboxes. Here are the 4 components I have: App.vue, test-filter.vue, filtersIn ...

Ways to determine the position of elements when they are centered using `margin:auto`

Is there a more efficient way to determine the position of an element that is centered using CSS margin:auto? Take a look at this fiddle: https://jsfiddle.net/vaxobasilidze/jhyfgusn/1/ If you click on the element with the red border, it should alert you ...

Retrieve the $root instance in Vuex actions

I have a Loader component that is triggered to execute based on certain conditions. created() { this.$root.$on('show-loading', (vars) => { this.loading = vars; console.log('loader executed'); }); }, Currently ...

The Runtime Error encountered in NEXTJS: TypeError - Unable to iterate over 'games' as it is not

Attempting to create my inaugural website that showcases data from an API sans a tutorial. Does it seem like I may have overlooked something? I've successfully fetched the API and confirmed in the console log that the necessary data is present. Howev ...

Building a remote shell using Node.js with the ability to interpret control sequences

Currently, I am working on developing a remote shell using Node.js. Here's the code that I have implemented so far : Client var net = require('net'); var client = net.connect({port: 1234}, function(){ process.stdin.pipe(client); clien ...

Adding a MTL texture to an OBJ in your three.js project is a simple process that can enhance

Hello! I am currently working on adding an MTL file to my OBJ in three.js. I had successfully loaded my OBJ and went back to address this issue. However, after adding the code to load the MTL file using MTLLoader, the code seems to be getting stuck at mt ...

Tips for submitting a checkbox value even when it is disabled

I attempted to make the checkbox readonly, but users were still able to check/uncheck the field. Next, I tried disabling the checkbox which successfully prevented user interaction. However, when attempting to submit the form, the disabled checkbox value ...

"When using FireFox, you can easily create a hyperlink that scrolls to a specific section of a webpage,

I have created a style for image button: .sticky { position: fixed; top: 50px; width: 120%; z-index: 1; } @media screen and (min-device-width : 100px) and (max-width: 600px) { .sticky{ display:none; } } and also implemented a script for it: ...

Learn how to manipulate the DOM by dynamically creating elements and aligning them on the same line

Providing some context for my page: The section I have always contains a single input field. Below that, there is an "add" button which generates additional input fields. Since only one field is required on the screen, the following fields come with a "de ...

Loading Data into Array - Angular/Ionic

I am currently developing an App and encountering issues with pushing data into an array. It seems that there is a problem in my code. Would you mind taking a look? Error Message Thrown: ionic.bundle.js:25642 TypeError: Cannot read property 'title&ap ...

show a fresh new page using react router

I have recently developed a mobile app that showcases a collection of movies. Currently, it is static and I am looking to implement a react router for navigation. Specifically, I want the user to be directed to a detail page for a TV Show when they click o ...

When executing npm run server, an error is generated saying: "sh: 1: vue-cli-service: not

I encountered an issue while setting up an existing vue project and received the following error message: admin@kali:/media/veracrypt1/themeforest-LSerfC0M-skote-vuejs-admin-dashboard-template/Admin$ npm run serve > <a href="/cdn-cgi/l/email-protec ...

Having difficulty accessing the ::after element on Firefox when attempting to click

I've encountered an issue with my HTML and CSS code - it functions perfectly on Chrome, yet behaves differently on Firefox. button#groupToggle { background: 0 0; border: 1px solid #e6e6ed; color: #222; float: none; margin: 0 0 ...

Utilizing AngularJS and RequireJS for intricate routing within web applications

I have encountered an issue with nested routings that I am struggling to resolve. The technologies I am using include: AngularJS, RequireJS; AngularAMD, Angular Route. To start off, here is my main routing setup: app.config(function($routeProvider, $loc ...

The webpage is missing a rendered React component even though it should be displayed

I am facing an issue where a React component is not appearing on the webpage despite being rendered. I have provided the code and screenshots of the components below for reference. Below is the snippet from the "App.jsx" file: function createCard ...

Steps to indicate a cucumber test as incomplete using a callback function in a node environment

Can a cucumber test in Node be flagged as pending to prevent automated test failures while still specifying upcoming features? module.exports = function() { this.Given(/^Scenario for an upcoming feature$/, function(callback) { callback(); } ...

Reload the MEN stack webpage without the need to reload the entire page

I am in the process of developing a data analytics dashboard using the MEN stack (MongoDB, Express.js, Node.js). I have successfully implemented functionality to display real-time data that refreshes every 5 seconds without the need to reload the entire ...