Dynamic Buttons in Navigation Bar using Vuetify - vue.js

I have a problem...
My VueJS Application using Vuetify.
I have a <v-toolbar>, and on the right, I want to place some buttons that change depending on the component shown in <router-view>, but i can't access to component properties from $route or $route for get objects and methods bind to model of my component.
I would like to know if there is any way to assign a model to from my main component.
I have tried with "named-routes" but I do not know what is the way that properties can be shared between components that are managed by an <router-view> and updated live.
In resume:
I have my application skeleton with a navigation bar, additionally in the dynamic content I have a <router-view>. Depending on the component that is displayed in <router-view>, I would like to see buttons in the navigation bar corresponding to that component, which interact and change the data or execute methods of the component.
App.vue
<template>
<v-app>
<router-view></router-view>
</v-app>
</template>
<script>
export default {
name: 'App',
data() {
return {
};
}
};
</script>
index.js (router)
import Vue from 'vue'
import Router from 'vue-router'
import AppLogin from '#/components/AppLogin'
import Skeleton from '#/components/Skeleton'
import ShoppingCart from '#/components/ShoppingCart'
import ShoppingCartButtons from '#/components/ShoppingCartButtons'
import ProductSelection from '#/components/ProductSelection'
import ProductSelectionButtons from '#/components/ProductSelectionButtons'
import ProductDetail from '#/components/ProductDetail'
Vue.use(Router)
export default new Router({
routes: [
{
path : '/login',
name : 'AppLogin',
component : AppLogin
},
{
path : '/app',
name : 'Skeleton',
component : Skeleton,
children : [{
path : 'shopping-cart',
components : {
navigation : ShoppingCart,
navButtons : ShoppingCartButtons
}
}, {
path: 'product-selection',
name : 'ProductSelection',
components : {
navigation : ProductSelection,
navButtons : ProductSelectionButtons
}
},
{
path: 'product-detail',
name : 'ProductDetail',
components : {
navigation : ProductDetail
},
props : true
}
]
}
]
})
Skeleton.vue
<template>
<v-container fluid>
<v-navigation-drawer
persistent
:mini-variant="miniVariant"
:clipped="true"
v-model="drawer"
enable-resize-watcher
fixed
app
>
<v-list>
<v-list-tile
value="true"
v-for="(item, i) in items"
:key="i"
:to="item.path">
<v-list-tile-action>
<v-icon v-html="item.icon"></v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title v-text="item.title"></v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</v-list>
</v-navigation-drawer>
<v-toolbar
app
:clipped-left="clipped"
>
<v-toolbar-side-icon #click.stop="drawer = !drawer">
</v-toolbar-side-icon>
<v-toolbar-title v-text="$route.meta.title"></v-toolbar-title>
<v-spacer></v-spacer>
<router-view name="navButtons"></router-view>
</v-toolbar>
<v-content>
<router-view name="navigation"/>
</v-content>
<v-footer :fixed="true" app>
<p style="text-align : center; width: 100%">© CONASTEC 2018</p>
</v-footer>
</v-container>
</template>
<script>
export default {
data() {
return {
clipped: true,
drawer: false,
fixed: false,
items: [
{
icon: "shopping_cart",
title: "Carrito de Compras",
path : "/app/shopping-cart"
},
{
icon: "attach_money",
title: "Facturas"
},
{
icon: "account_balance_wallet",
title: "Presupuestos"
},
{
icon: "insert_chart",
title: "Informes"
},
{
icon: "local_offer",
title: "Productos"
},
{
icon: "person",
title: "Clientes"
},
{
icon: "layers",
title: "Cuenta"
},
{
icon: "comment",
title: "Comentarios"
},
{
icon: "settings",
title: "Ajustes"
}
],
buttons : [],
miniVariant: false,
right: true,
rightDrawer: false
};
},
name: "Skeleton"
};
</script>
EDITED
My solution is create a new component Toolbar and add slots for buttons to right and left.
<template>
<div>
<v-navigation-drawer persistent :mini-variant="false" :clipped="true" v-model="drawer" enable-resize-watcher fixed app>
<v-list>
<v-list-tile value="true" v-for="(item, i) in items" :key="i" :replace="true" :to="item.path">
<v-list-tile-action>
<v-icon v-html="item.icon"></v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title v-text="item.title"></v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</v-list>
</v-navigation-drawer>
<v-toolbar app :clipped-left="true" color="primary" :dark="true" flat>
<v-toolbar-side-icon v-if="showDrawer" #click.stop="drawer = !drawer">
</v-toolbar-side-icon>
<v-toolbar-side-icon v-if="!!back" #click="back">
<v-icon>keyboard_backspace</v-icon>
</v-toolbar-side-icon>
<v-toolbar-title v-text="title" style="font-size: 1.4em"></v-toolbar-title>
<v-spacer></v-spacer>
<v-card-actions>
<slot name="right"></slot>
</v-card-actions>
</v-toolbar>
<v-snackbar
:timeout="5000"
:top="true"
:multi-line="true"
:vertical="true"
v-model="snackbar.show"
>
{{ snackbar.content }}
<v-btn flat color="white" #click.native="snackbar.show = false">Cerrar</v-btn>
</v-snackbar>
</div>
</template>
<script>
export default {
name: 'app-toolbar',
props: ['title','showDrawer', 'back'],
data() {
return {
drawer : false,
items: [{
icon: "shopping_cart",
title: "Carrito de Compras",
path: "/carrito-compras"
}, {
icon: "attach_money",
title: "Facturas",
path: "/documentos-tributarios"
}, {
icon: "account_balance_wallet",
title: "Presupuestos"
}, {
icon: "insert_chart",
title: "Informes"
}, {
icon: "local_offer",
title: "Productos"
}, {
icon: "person",
title: "Clientes"
}, {
icon: "layers",
title: "Cuenta"
}, {
icon: "comment",
title: "Comentarios"
}, {
icon: "settings",
title: "Ajustes"
}]
};
},
computed : {
snackbar() {
return this.$store.getters.snackbar;
}
}
}
</script>
and use is:
<app-toolbar title="Carrito de Compras" :showDrawer="true">
<template slot="right">
<v-toolbar-side-icon #click="confirm">
<v-icon>monetization_on</v-icon>
</v-toolbar-side-icon>
</template>
</app-toolbar>

I did the same thing as you in a recent project and found altering the structure was the easier way to fix issues like this.
My structure was as follows:
app.vue: Only contains <router-view> no other components
router.js: Parent route is a layout component, all sub routes which contains my toolbars and other layout components and it's own <router-view> which receives child routes
ex:
{
path: '/login',
name: 'Login',
component: load('login')
},
{
path: '/',
component: load('main-layout'),
children: [
{
path: '',
name: 'Home Page',
component: load('homePage')
},
{
path: '/settings',
name: 'Settings',
component: load('settings'),
}
]
}
Now in your main-layout:
computed: {
showHomeButton () {
if (this.$route.path === '/') {
return true
}
return false
// Repeat for other routes, etc...
},
}

If you are using Vuex, you can use vuex-router-sync, then you can
access the route from any component with this.$state.route.path.
If not, Scott's answer is probably the best way to do it.

I had the same problem, My solution was manage the left button action from de meta of vue router like this:
{
path: '/feedstocks/:categoryId/:id',
name: 'Feedstock',
component: () =>
import(
/* webpackChunkName: "client-chunk-feedstock-details" */ '#/views/FeedstockDetails.vue'
),
props: true,
meta: {
authNotRequired: true,
backRoute: 'Material'
}
}
Then I'm able to check that metadata in app bar button action:
<v-app-bar app color="primary" dark>
<v-btn text icon color="white" #click="leftButtonAction">
<v-icon>{{ leftButtonIcon }}</v-icon>
</v-btn>
<v-toolbar-title>
{{ currentAppTitle }}
</v-toolbar-title>
<v-spacer></v-spacer>
</v-app-bar>
leftButtonIcon() {
if (this.$route.meta.backRoute) {
return 'mdi-chevron-left'
}
return 'mdi-menu'
}
leftButtonAction() {
if (this.$route.meta.backRoute) {
this.$router.push({ name: this.$route.meta.backRoute })
} else {
this.toggleDrawer()
}
}

I guess it's a time for a more up-to-date answer.
For my requirement to dynamically modify the item list in the app-bar based on the selected view, the solution was to use the Named Views

Related

Vue: I want to send data to another page

I have a page that lists employees.
<template>
<v-container>
<v-card
class="mb-6 pa-2 mx-auto rounded-lg"
max-width="1000"
color=""
v-for="user in users"
:key="user.id"
>
............
<v-btn
class="mb-3 mt-3"
v-on:click="sendConfirm(user.ID)"
to="/companyApplicants/menteeListPage"
color="green"
>
<v-icon>mdi-clipboard-account</v-icon>
</v-btn>
...........
</v-col>
</v-list-item>
</v-card>
</v-container>
</template>
<script>
export default {
data() {
return {
userDatas: [],
users: [
{
.....
},
],
}
},
mounted() {
this.getUserData()
},
methods: {
getUserData() {
return this.$axios.$get('/api/MyMentors').then((response) => {
this.users = response
console.log(response)
})
},
},
}
</script>
And when they press the button and go to the other page I want to send Id of the clicked mentor. I can get the Id but couldn't figure out how to send that Id to the other page
you can add the id to the route
<v-btn
class="mb-3 mt-3"
v-on:click="sendConfirm(user.ID)"
:to="`/companyApplicants/menteeListPage/${user.ID}`"
color="green"
>
<v-icon>mdi-clipboard-account</v-icon>
</v-btn>
just need to update your route to have the data available there
{
path: "/companyApplicants/menteeListPage/:userID",
name: "menteeListPage",
component: () => import(/* webpackChunkName: "views" */ "./views/MenteeListPage.vue"),
meta: {
requiresAuth: true,
title: "Menteen List Page {{userID}}",
},
},
your variable will then be accessible in the vue components through this.$route.params.userID
If you want to make it optional for the route use ? at the end :
path: "/companyApplicants/menteeListPage/:userID?",

Vue.js – New routes are always placed on top of current route

In my Vue.js application I use a navigation drawer on the left side of the screen for navigation purposes. I am using Vuetify and Vue Router.
Problem
After changing my routes a lot of my previously routing functionalities got messed up. Whenever a user clicks on an element to navigate to a new site the route get's attached on top of the previous one like this.
Route before a user clicks on a link:
http://localhost:8080/organization/:organization_id/planner/events
New route after a user clicks on a link:
http://localhost:8080/organization/:organization_id/planner/management/contracts
Router
routes: [
// Login
{
path: '/login',
component: Login,
},
// Organization
{
path: '/organization',
component: Organization,
},
// Organization Detail Page
{
path: '/organization/:organization_id',
component: OrganizationDetail,
children: [
// Module: Planner
{
path: 'planner',
component: Planner
},
// Planner > Events
{
path: 'planner/events',
component: Events
},
{
path: 'planner/events/new',
component: NewEvent
},
{
path: 'planner/events/details/:event_id',
component: EventDetails
},
// Planner > Calendar
{
path: 'planner/calendar',
component: Calendar
},
// Module: Management
{
path: 'management',
component: Management
},
// Management > Users
{
path: 'management/users',
component: Events
},
{
path: 'management/users/new',
component: NewUser
},
{
path: 'management/users/details/:user_id',
component: UserDetails
},
// Planner > Contracts
{
path: 'management/contracts',
component: Contracts
}
]
}
]
NavigationDrawer.vue (updated):
<template>
<div id="navigation">
<nav>
<v-navigation-drawer
v-model="drawer"
:clipped="$vuetify.breakpoint.lgAndUp"
width="400"
fixed
app
>
<v-list>
<template v-for="item in items">
<v-row
v-if="item.heading"
:key="item.heading"
align="center"
>
</v-row>
<v-list-group
v-else-if="item.children"
:key="item.text"
v-model="item.model"
append-icon="mdi-chevron-down"
class="nav"
link
router :to="item.route"
>
<v-list-item
v-for="(child, i) in item.children"
:key="i"
link
router :to="child.route"
>
<v-list-item-action v-if="child.icon">
<v-icon>{{ child.icon }}</v-icon>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title>
{{ child.text }}
</v-list-item-title>
</v-list-item-content>
</v-list-item>
</v-list-group>
</template>
</v-list>
</v-navigation-drawer>
<v-app-bar
:clipped-left="$vuetify.breakpoint.lgAndUp"
app
dark
>
<v-app-bar-nav-icon #click.stop="drawer = !drawer"></v-app-bar-nav-icon>
</v-app-bar>
</nav>
</div>
</template>
<script>
export default {
name: 'NavigationDrawer',
el: '#app',
data: () => ({
drawer: true,
menu: false,
items: [
{
text: 'Planner',
children: [
{ text: 'Events', route:'/organization/' + this.$route.params.organization_id + '/planner/events'},
{ text: 'Calendar', route:'/organization/' + this.$route.params.organization_id + '/planner/calendar'}
],
},
{
text: 'Management',
children: [
{ text: 'Users', route:'/organization/' + this.$route.params.organization_id + '/management/users'},
{ text: 'Contracts', route:'/organization/' + this.$route.params.organization_id + '/management/contracts'}
],
},
]
}),
methods: {
logout() {
// some awesome stuff
}
}
}
</script>
Other routes like (NewUser, NewEvent) are not stored in the navigation drawer and called manually by a button.
I know that this has something to do with my routes. However those aren't misconfigured because the relations between parent and children are important for displaying the right content and implementing some header informations. The navigation drawer works also the right way. I didn't change anything there.
Also if I use router.back() on NewEvent or NewUser nothing happens. :(
Help is very much appreciated, thanks!
The issue is because of
{ text: 'Events', route:'/planner/events'},
The above route redirects the website to http://localhost:8080/planner/events because of initial forward slash.
Use the $route.params to get params from URL like the following.
<div>User {{ $route.params.organization_id }}</div>
or
this.$route.params.organization_id

Separate navigation drawers for certain routes in vue-router

I'm building a Vuetify app in combination with Vuex and vue-router. Some of the views uses the default navigation drawer, but others has different items in their navigation drawers. This documentation say I can pass props to view components. So I implement it like this:
routes/index.js
{
path: '/courses/:courseId/lessons/:lessonId',
name: 'Course 1',
components: {
default: () => import('#/views/ViewLesson.vue'),
sidebar: () => import('#/components/CourseNavBar/CourseNavBar.vue')
},
props: {
items: [
{ text: "Link 1", href:"/link1" },
{ text: "Link 2", href:"/link2" }
]
}
}
src/App.vue
<template>
<v-app>
<v-app-bar
app
color="primary"
dark
>
<h1>My Project</h1>
</v-app-bar>
<v-navigation-drawer><router-view :items="items" name="sidebar"/></v-navigation-drawer>
<v-content>
<router-view />
</v-content>
</v-app>
</template>
But apparently,
src/components/CourseNavBar.vue
<template>
<!-- <v-navigation-drawer :value="1"> -->
<v-list dense>
<navbar-item v-for="(item, i) in items" :key="i" :item="item" >
{{ item.text }}
</navbar-item>
</v-list>
<!-- </v-navigation-drawer> -->
</template>
<script>
import NavBarItem from './NavBarItem.vue'
export default {
props: {
items: Array
},
components: {
'navbar-item': NavBarItem
}
}
</script>
But <CourseNavBar>'s props is still undefined. What am I doing wrong here?
There are a few issues...
Replace = with :...
items: [
{ text:"Link 1", href:"/link1" },
{ text:"Link 2", href:"/link2" }
]
And the sidebar component (not router-view) should be in the slot for the navigation-drawer...
<v-navigation-drawer><sidebar :items="items"></sidebar></v-navigation-drawer>
Demo: https://codeply.com/p/oNInfpTwvK
In your
routes\index.js
you need to define the props option for each of the named views:
{
path: '/courses/:courseId/lessons/:lessonId',
name: 'Course 1',
components: {
default: () => import('#/views/ViewLesson.vue'),
sidebar: () => import('#/components/CourseNavBar/CourseNavBar.vue')
},
props: {
default: true,
sidebar: true,
items: [
{ text: "Link 1", href: "/link1" },
{ text: "Link 2", href: "/link2" }
]
}
}
And following on from what #Zim said, you've used "=" instead of ":" when assigning the href value to the props items array.
You can use <router-view name="sidebar"/> to output the named component.

Vue-i18n: how to save the selected locale

There is a site on vue to which i18n library is connected.There is a button for switching languages.
<div class="locale-changer">
<v-menu v-model="changeLocaleState" offset-y>
<template v-slot:activator="{ on }">
<v-btn
color="primary"
dark
v-on="on"
/>
</template>
<v-list>
<v-list-tile
v-for="(lang, i) in langs"
:key="`lang.lacale${i}`"
:value="lang.locale"
#click="$i18n.locale = lang.locale"
>
<v-list-tile-title><img :src="lang.img">{{ lang.locale }}</v-list-tile-title>
</v-list-tile>
</v-list>
</v-menu>
export default {
name: 'VeLanguageSwitcher',
data () {
return { langs: [
{
name: 'en',
locale: 'en-US',
img: '/assets/img/flag/GB.png'
},
{
name: 'ru',
locale: 'ru-RU',
img: '/assets/img/flag/RU.png'
}
] }
},
computed: {
changeLocaleState: {
get () {
return this.$store.state.ui.changeLocale
},
set (val) {
this.$store.commit('ui/setChangeLocale', val)
}
}
}
}
</script>
The selected locale is not saved.Theoretically, I understand that when choosing a language you make SET in vuex, and GET displays a picture of the current locale inside the button.But I don't know how to do it

How to use vuetify component v-navigation-drawer, toolbar, footer separately in different files

I am trying to implement the vuetify in my project. I wanted to separate the
<v-navigation-drawer>, </v-toolbar> and <v-footer> in three different files.
Currently i am using.
Layout.vue
<template>
<v-app>
<TopNav :drawer="drawer" :clipped="clipped"></TopNav>
<SideBar/>
<v-content>
<v-container fluid>
<router-view></router-view>
</v-container>
</v-content>
<FooterArea/>
</v-app>
</template>
Script- Layout.vue
<script>
import { TopNav, FooterArea, SideBar } from "../layouts/index";
export default {
name: "Full",
components: {
TopNav,
FooterArea,
SideBar
},
data() {
return {
clipped: true,
drawer: true,
fixed: false,
inset: true,
items: [
{
icon: "bubble_chart",
title: "Inspire"
}
],
miniVariant: false,
right: true,
rightDrawer: false,
title: "Vuetify.js"
};
}
};
</script>
TopNav.vue
<template>
<v-toolbar dark color="info" app :clipped-left="clipped">
<v-toolbar-side-icon v-model="drawer" #click.stop="drawer = !drawer"></v-toolbar-side-icon>
<v-toolbar-title class="white--text">Title</v-toolbar-title>
</v-toolbar>
</template>
<script>
export default {
props: {
clipped: {
type: Boolean,
default: true
},
drawer: {
type: Boolean,
default: true
}
}
};
</script>
SideBar.vue
<template>
<v-navigation-drawer
persistent
:mini-variant="miniVariant"
:clipped="clipped"
v-model="drawer"
enable-resize-watcher
fixed
app
>
<v-list>
<v-list-tile
value="true"
v-for="(item, i) in items"
:key="i"
>
<v-list-tile-action>
<v-icon v-html="item.icon"></v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title v-text="item.title"></v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</v-list>
</v-navigation-drawer>
</template>
<script>
export default {
}
</script>
However have tried by using the props and passing the values from Layout.vue to TopNav.vue, but i am getting the error as:
Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "drawer"
As I need to emit from the TopNav.vue to Layout.vue but i couldnot understand how it can be done nicely.
Thank you in advance for the help.
I use it like this:
Parent
<template>
<v-app id="inspire">
<TheNavDrawer :items="items" v-model="drawer" />
<v-toolbar
:clipped-left="$vuetify.breakpoint.lgAndUp"
color="orange darken-3"
dark
app
fixed
>
<v-toolbar-side-icon
#click.stop="drawer = !drawer"
class="hidden-xs-only"
/>
<v-toolbar-title>Test App</v-toolbar-title>
</v-toolbar>
</v-app>
</template>
<script>
import TheNavDrawer from "#/components/Navigation/TheNavDrawer";
export default {
data: () => ({
drawer: false,
items: [
{ icon: "contacts", text: "Contacts" },
{ icon: "history", text: "Frequently contacted" },
{ icon: "content_copy", text: "Duplicates" },
{
icon: "keyboard_arrow_up",
"icon-alt": "keyboard_arrow_down",
text: "Labels",
model: true,
children: [{ icon: "add", text: "Create label" }]
},
{
icon: "keyboard_arrow_up",
"icon-alt": "keyboard_arrow_down",
text: "More",
model: false,
children: [
{ text: "Import" },
{ text: "Export" },
{ text: "Print" },
{ text: "Undo changes" },
{ text: "Other contacts" }
]
},
{ icon: "settings", text: "Settings" },
{ icon: "chat_bubble", text: "Send feedback" },
{ icon: "help", text: "Help" },
{ icon: "phonelink", text: "App downloads" },
{ icon: "keyboard", text: "Go to the old version" }
]
}),
components: {
TheNavDrawer,
}
};
</script>
TheNavDrawer.vue
<template>
<v-navigation-drawer
v-bind:value="value" # <-- mimic v-model behaviour
v-on:input="$emit('input', $event)" <-- mimic v-model behaviour
:clipped="$vuetify.breakpoint.lgAndUp"
fixed
app
>
<v-list dense>
<template v-for="item in items">
<v-layout v-if="item.heading" :key="item.heading" row align-center>
<v-flex xs6>
<v-subheader v-if="item.heading">
{{ item.heading }}
</v-subheader>
</v-flex>
<v-flex xs6 class="text-xs-center">
EDIT
</v-flex>
</v-layout>
<v-list-group
v-else-if="item.children"
:key="item.text"
v-model="item.model"
:prepend-icon="item.model ? item.icon : item['icon-alt']"
append-icon=""
>
<v-list-tile slot="activator">
<v-list-tile-content>
<v-list-tile-title>
{{ item.text }}
</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
<v-list-tile
v-for="(child, i) in item.children"
:key="i"
#click="false"
>
<v-list-tile-action v-if="child.icon">
<v-icon>{{ child.icon }}</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title>
{{ child.text }}
</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</v-list-group>
<v-list-tile v-else :key="item.text" #click="false">
<v-list-tile-action>
<v-icon>{{ item.icon }}</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title>
{{ item.text }}
</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</template>
</v-list>
</v-navigation-drawer>
</template>
<script>
export default {
props: {
items: {
type: Array,
required: true
},
value: {
type: Boolean,
default: false
}
}
};
</script>
Basically, instead of using v-model inside the NavDrawer child component I define my own v-model with v-bind:value="value" and v-on:input="$emit('input', $event)" which propagates the status from the <v-navigation-drawer> up to the parent component and makes for much cleaner code. If you want to know more about what happens behind the scenes look here: https://v2.vuejs.org/v2/guide/components-custom-events.html
This is how I use navigation drawer as Parent/Child components without using vuex state management.
Parent Compontent
<Drawer :items="navigations.user.items" :drawer="navigations.user.drawer" #drawerStatus="navigations.user.drawer = $event" :position="navigations.user.position" :avatar="navigations.user.avatar" />
<v-toolbar color="transparent" flat dark absolute>
<v-toolbar-side-icon #click.native.stop="navigations.default.drawer = !navigations.default.drawer">
</v-toolbar-side-icon>
<v-toolbar-title>Open Voucher</v-toolbar-title>
<v-spacer></v-spacer>
<v-btn icon>
<v-icon #click.native.stop="navigations.user.drawer = !navigations.user.drawer">more_vert</v-icon>
</v-btn>
</v-toolbar>
</div>
</template>
<script>
import Drawer from './Drawer'
export default {
components: {
Drawer
},
data () {
return {
drawer: null,
navigations:
{
default: {
drawer: false,
position: null,
avatar: false,
items: [
{ title: 'Item title', icon: 'fas fa-home', url: '/' },
{ title: 'Item title', icon: 'fas fa-user-friends', url: '/item-url' },
{ title: 'Item title', icon: 'fas fa-atlas', url: '/item-url' },
{ title: 'Item title', icon: 'fas fa-archway', url: '/item-url' },
{ title: 'Item title', icon: 'fas fa-pencil-alt', url: '/item-url' }
]
},
user: {
drawer: false,
position: 'right',
avatar: true,
items: [
{ title: 'Item title', icon: 'dashboard', url: '/item-url' },
{ title: 'Item title', icon: 'fas fa-map-marked-alt', url: '/item-url' },
{ title: 'Item title', icon: 'fas fa-heart', url: '/item-url' },
{ title: 'Item title', icon: 'question_answer', url: '/item-url' }
]
}
}
}
},
methods: {
changeDrawerStatus(value) {
this.drawer = value;
}
}
}
</script>
Child Component
<template>
<v-navigation-drawer v-model="drawerChild" fixed temporary app :right="position">
<v-list class="pa-1" v-if="avatar">
<v-list-tile avatar>
<v-list-tile-avatar>
<img src="https://randomuser.me/api/portraits/men/85.jpg">
</v-list-tile-avatar>
<v-list-tile-content>
<v-list-tile-title>John Leider</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</v-list>
<v-list class="pt-0" dense>
<v-divider></v-divider>
<v-list-tile v-for="item in itemList" :key="item.title" :to="item.url">
<v-list-tile-action>
<v-icon>{{ item.icon }}</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title>{{ item.title }}</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</v-list>
</v-navigation-drawer>
</template>
<script>
export default {
props: [
'items',
'drawer',
'position',
'avatar'
],
data() {
return {
drawerChild: null,
itemList: []
}
},
mounted() {
this.itemList = this.items;
},
watch: {
drawer (value) {
this.drawerChild = value;
},
drawerChild (value) {
this.$emit('drawerStatus', value)
}
}
}
</script>