Reputation: 1075
Like the title says, I'm trying to have a navigation drawer that has expandable sub-menus for certain options. Like a "User Profile" main menu option might have a the sub-menus "Update Contact Details" and "Review Registration".
I've tried this a handful of ways, basically coming down to the same two issues. Because each menu options is a list-tile, either the sub-menu gets stacked on the right of it (as in, the entire sub-menu is in the same tile), or the entire list of menu options has these drop down icons, when only a single menu option actually has a sub-menu. Additionally, my second code snippet below also stops you from navigating to any of the main menu links, which is not what is wanted.
Example 1, where the sub-menu is stuck in the same tile as the main menu option.
<div v-for="(link, i) in links" :key="i">
<v-list-tile v-if="!link.subLinks" :to="link.to" :active-class="color" avatar class="v-list-item">
<v-list-tile-action>
<v-icon>{{ link.icon }}</v-icon>
</v-list-tile-action>
<v-list-tile-title v-text="link.text"/>
</v-list-tile>
<div v-else>
<v-list-tile avatar class="v-list-item">
<v-list-tile-action>
<v-icon>{{ link.icon }}</v-icon>
</v-list-tile-action>
<v-list-tile-title v-text="link.text"/>
<v-list-group>
<v-list-tile sub-group v-for="(subLink, j) in link.subLinks" :key="j" :to="subLink.to" :active-class="color" avatar class="v-list-item">
<v-list-tile-title v-text="subLink.text"/>
</v-list-tile>
</v-list-group>
</v-list-tile>
</div>
</div>
Example 2, where each menu option has a drop down arrow, even ones that don't have any sub-menus.
<v-list-group v-for="(link, i) in links" :key="i" :prepend-icon="link.icon" :to="link.to" :active-class="color" avatar class="v-list-item">
<template v-slot:activator>
<v-list-tile>
<v-list-tile-title>{{ link.text }}</v-list-tile-title>
</v-list-tile>
</template>
<v-list-tile v-for="(subLink, j) in link.subLinks" :key="j" :to="subLink.to" :active-class="color">
<v-list-tile-content>
<v-list-tile-title>{{ subLink.text }}</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</v-list-group>
This is a sample of the data I'm using
links: [
{
to: '/',
icon: 'mdi-view-dashboard',
text: 'Dashboard',
},
{
icon: 'mdi-account',
text: 'User Profile',
subLinks: [
{
to: '/update-contact',
text: 'Update Contact Details',
},
{
to: '/review-registration',
text: 'Review Registration',
},
],
},
],
What I'd like to be able to do is have a main menu, with the option of adding sub-menus as I see fit. Unfortunately, I can't seem to figure out how to mix and match the list-group and list-tile to get what I want done. I'm super grateful for any help provided. Thanks.
Upvotes: 14
Views: 26608
Reputation: 135
This is three level category list item with navigation-drawer. This is actually find vuetify list section. then i modified this with three level item. You can extend and also optimized code. Just for example I write raw code.
<v-navigation-drawer
v-model="drawer"
:clipped="clipped"
fixed
app
>
<v-list nav dense>
<v-list-item
to="/"
>
<v-list-item-icon>
<v-icon>mdi-home</v-icon>
</v-list-item-icon>
<v-list-item-title>Home</v-list-item-title>
</v-list-item>
<!--Main category list-->
<v-list-group
v-for="item in items"
:value="true"
prepend-icon="mdi-food-apple"
no-action
>
<template v-slot:activator>
<v-list-item-title>{{item.name}}</v-list-item-title>
</template>
<!--Sub category item-->
<!--if 2nd lvl child available-->
<v-list-group
v-if="subItem.children.length > 0"
v-for="subItem in item.children"
:value="true"
sub-group
>
<template v-slot:activator>
<v-list-item-content>
<v-list-item-title>{{subItem.name}}</v-list-item-title>
</v-list-item-content>
</template>
<!--subsubitem category list-->
<v-list-item v-for="subSubItem in subItem.children"
:to="'/category/'+subSubItem.slug">
<v-list-item-icon>
<v-icon></v-icon>
</v-list-item-icon>
<v-list-item-title>{{subSubItem.name}}</v-list-item-title>
</v-list-item>
</v-list-group>
<!--if not 2nd lvl child available-->
<v-list-item :to="'/category/'+subItem.slug" v-for="subItem in
item.children">
<v-list-item-icon>
<v-icon></v-icon>
</v-list-item-icon>
<v-list-item-title>{{subItem.name}}</v-list-item-title>
</v-list-item>
</v-list-group>
</v-list>
</v-navigation-drawer>
DATA:
[
{
"id": 1,
"name": "Food",
"slug": "food",
"children": [
{
"id": 2,
"name": "Fruits & Vegetables",
"slug": "fruits-vegetables",
"children": [
{
"id": 3,
"name": "Fresh Fruits",
"slug": "fresh-fruit",
"children": []
},
{
"id": 4,
"name": "Fresh Vegetables\r\n",
"slug": "fresh-vegetable",
"children": []
}
]
},
{
"id": 5,
"name": "Breakfast",
"slug": "breakfast",
"children": [
{
"id": 6,
"name": "Local Breakfast",
"slug": "local-breakfast",
"children": []
}
]
}
]
},
{
"id": 7,
"name": "Home & Cleaning",
"slug": "home-cleaning",
"children": [
{
"id": 8,
"name": "Air Fresheners",
"slug": "air-freshners",
"children": []
},
{
"id": 9,
"name": "Cleaning Supplies",
"slug": "cleaning-supplies",
}
]
}
]
Upvotes: 1
Reputation: 1
I just found a way to set the submenu active-class. Hope it can help others. thanks to VueJS-Linusborg.
<template>
......
<v-list-group
v-else
:key="link.text"
no-action
:prepend-icon="link.icon"
:value="subIsActive('/parentroute')"
>
<template v-slot:activator>
<v-list-item-title>{{ link.text}}</v-list-item-title>
</template>
<v-list-item
v-for="sublink in link.subLinks"
:to="sublink.to"
:key="sublink.text"
:active-class="`success white--text`"
>
<v-list-item-icon>
<v-icon>{{ sublink.icon }}</v-icon>
</v-list-item-icon>
<-list-item-title>{{ sublink.text}}</v-list-item-title>
</v-list-item>
</v-list-group>
...
</template>
<script>
...
methods:{
subIsActive(input) {
const paths = Array.isArray(input) ? input : [input];
return paths.some((path) => {
return this.$route.path.indexOf(path) === 0; // current path starts with this path
string
});
},
....
}</script>
Upvotes: 0
Reputation: 159
I don't have enough reputation to add a comment but this will give you a bit of a better layout and function correctly (in the one posted above links didn't work for some reason and the naming was a bit off)
<template>
<v-navigation-drawer
app
clipped
permanent
mini-variant
expand-on-hover>
<!-- -->
<v-list nav dense>
<div v-for="(link, i) in links" :key="i">
<v-list-item
v-if="!link.subLinks"
:to="link.to"
:active-class="color"
avatar
class="v-list-item"
>
<v-list-item-icon>
<v-icon>{{ link.icon }}</v-icon>
</v-list-item-icon>
<v-list-item-title v-text="link.text" />
</v-list-item>
<v-list-group
v-else
:key="link.text"
no-action
:prepend-icon="link.icon"
:value="false"
>
<template v-slot:activator>
<v-list-item-title>{{ link.text }}</v-list-item-title>
</template>
<v-list-item
v-for="sublink in link.subLinks"
:to="sublink.to"
:key="sublink.text"
>
<v-list-item-icon>
<v-icon>{{ sublink.icon }}</v-icon>
</v-list-item-icon>
<v-list-item-title>{{ sublink.text }}</v-list-item-title>
</v-list-item>
</v-list-group>
</div>
</v-list>
</v-navigation-drawer>
</template>
<script>
export default {
data: () => ({
links: [
{
to : '/dashboard',
icon : 'mdi-view-dashboard',
text : 'Dashboard',
},
{
icon : 'mdi-folder',
text : 'Templates',
subLinks : [
{
text : 'View Templates',
to : '/templates',
icon : 'mdi-view-list'
},
{
text : 'New Template',
to : '/templates/new',
icon : 'mdi-plus'
},
]
},
{
icon : 'mdi-application',
text : 'Applications',
subLinks : [
{
text : 'View Applications',
to : '/apps',
icon : 'mdi-view-list'
},
{
text : 'New Application',
to : '/apps',
icon : 'mdi-plus'
},
]
},
]
})
}
</script>
<style scoped>
.v-application--is-ltr .v-list--dense.v-list--nav .v-list-group--no-action > .v-list-group__items > .v-list-item {
padding: 0 8px;
}
</style>
Upvotes: 13
Reputation: 867
Hope this can help. Basically, the menu on the navigation drawer component (v-navigation-drawer) using the list component (v-list).
From the documentation, you can find a way to add submenu on list component on the part of nested list
Cheers,
Upvotes: 3
Reputation: 345
I was looking to do the same thing, here's how I solved it.
Data:
links: [
{
to : '/dashboard',
icon : 'mdi-view-dashboard',
text : 'Dashboard',
},
{
icon : 'mdi-tennis',
text : 'Players',
subLinks : [
{
text : 'Players list',
to : '/players',
},
{
text : 'Import WTA Players',
to : '/players/import',
},
]
},
{
to : '/tournaments',
icon : 'mdi-trophy',
text : 'Tournaments',
},
]
Template:
<v-list>
<div v-for="(link, i) in links">
<v-list-tile
v-if="!link.subLinks"
:key="i"
:to="link.to"
:active-class="color"
avatar
class="v-list-item"
>
<v-list-tile-action>
<v-icon>{{ link.icon }}</v-icon>
</v-list-tile-action>
<v-list-tile-title v-text="link.text" />
</v-list-tile>
<v-list-group
v-else
:key="link.text"
no-action
>
<template v-slot:activator>
<v-list-tile>
<v-list-tile-content>
<v-list-tile-title>{{ link.text }}</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</template>
<v-list-tile
v-for="sublink in link.subLinks"
:to="sublink.to"
:key="sublink.text"
>
<v-list-tile-title v-text="sublink.text" />
</v-list-tile>
</v-list-group>
</div>
</v-list>
I'm sorry but I don't have time to make a pen. Hope this helps !
Upvotes: 14