Vuetify router alignment - vue.js

I'm trying to setup at route that contains just a table with a layout inspired by the Vuetify team.
I have a problem that the table does not take only a small part of the screen.
I have tried using v-layout with "row", "column" and different paddings and marging.
App.vue:
<template>
<v-app>
<router-view/>
</v-app>
</template>
<script>
export default {
name: 'App',
};
</script>
Menu.vue:
<template>
<v-container>
<v-navigation-drawer
clipped
fixed
v-model="drawer"
app
>
<v-list dense>
<v-list-tile
:to="{name: 'dashboard'}"
>
<v-list-tile-action>
<v-icon>dashboard</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title>Dashboard</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
<v-list-tile
:to="{name: 'settings'}"
>
<v-list-tile-action>
<v-icon>settings</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title>Settings</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
<v-list-tile
#click="logout();"
>
<v-list-tile-action>
<v-icon>logout</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title>Logout</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</v-list>
</v-navigation-drawer>
<v-toolbar app fixed clipped-left>
<v-toolbar-side-icon #click.stop="drawer = !drawer"></v-toolbar-side-icon>
<v-toolbar-title>Hello, {{ name }}</v-toolbar-title>
</v-toolbar>
<v-content>
<v-container fluid fill-height>
<v-layout justify-center align-center>
<v-flex shrink>
<router-view></router-view>
</v-flex>
</v-layout>
</v-container>
</v-content>
<v-footer app fixed>
<span>© arcyfelix 2019</span>
</v-footer>
</v-container>
</template>
<script>
export default {
name: 'MainMenu',
data() {
return {
drawer: false,
name: 'Wojciech',
};
},
methods: {
logout() {
this.$router.push({ name: 'home' });
},
},
};
</script>
Dashboard.vue:
<template>
<v-layout full-width>
<v-data-table
:items="desserts"
class="elevation-1"
hide-actions
hide-headers
expand
:loading="true"
>
<template v-slot:items="props">
<td class="text-xs-left">2019-07-01</td>
<td>{{ props.item.name }}</td>
<td>
<v-btn
small
depressed
flat
>
Edit
</v-btn>
</td>
</template>
</v-data-table>
</v-layout>
</template>
<script>
export default {
name: 'Dashboard',
data() {
return {
desserts: [
{
name: 'Frozen Yogurt',
},
{
name: 'Donut',
},
{
name: 'KitKat',
},
],
};
},
};
</script>
router.js:
import Vue from 'vue';
import Router from 'vue-router';
import Menu from './layouts/Menu.vue';
import MainMenu from './layouts/MainMenu.vue';
import Dashboard from './views/Dashboard.vue';
import Login from './views/Login.vue';
import Home from './views/Home.vue';
Vue.use(Router);
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: 'auth',
name: 'auth',
component: Menu,
children: [
{
path: 'dashboard',
name: 'dashboard',
component: Dashboard,
},
{
path: 'settings',
name: 'settings',
component: () => import(/* webpackChunkName: "about" */ './views/Settings.vue'),
},
],
},
{
path: '/',
name: 'mainMenu',
component: MainMenu,
children: [
{
path: 'home',
name: 'home',
component: Home,
},
{
path: 'login',
name: 'login',
component: Login,
},
{
path: 'register',
name: 'register',
component: () => import(/* webpackChunkName: "about" */ './views/Register.vue'),
},
],
},
],
});
I would like to take it 2/3 or full width of the screen.

What you really want is to put the menu outside of the router-view otherwise it has to reload on each page load. You also want to move the container definition inside of the v-content element and make sure it uses fill-height too less you end up with an odd background mesh.
<v-app>
<my-menu></my-menu>
<v-content>
<v-container fluid fill-height>
<router-view></router-view>
</v-container>
</v-content>
</v-app>
Now just change your Dashboard code and layout:
<v-layout row wrap>
<v-flex xs12>
//the rest of the dashboard code
</v-flex>
</v-layout
And you're good to go.

Related

Vuetify v-tab slider animation doesn't work with exact parameter in v-tab

I have problem with vuetify tabs.
Everything works fine, but when I add exact parameter to v-tab the bottom bar animation stops working.
Tabs display correctly but v-tabs-slider-wrapper position isn't updated.
Without exact parameter is ok.
How do I fix this animation?
routes.js
{
path: "/course",
component: Course,
children: [
{
path: "",
component: CourseDetails,
name: "courseDetails"
},
{
path: "lessons",
component: CourseLessons,
name: "courseLessons"
},
{
path: "reviews",
component: CourseReviews,
name: "courseReviews"
},
]
},
Course.vue
<template>
<v-container fluid>
<v-row>
<v-col>
<v-tabs v-model="activeTab" grow>
<v-tab to="/course" exact>Details</v-tab>
<v-tab to="/course/lessons" exact>Lessons</v-tab>
<v-tab to="/course/reviews" exact>Reviews</v-tab>
</v-tabs>
</v-col>
</v-row>
<v-row>
<v-col cols="12">
<router-view></router-view>
</v-col>
</v-row>
</v-container>
</template>
<script>
export default {
name: "Course",
data: () => ({
activeTab: null
})
};
</script>

How can I solve the issue with redirection?

I am setting up a new project on nuxt and I've made one new layout for a login page, and created a page login.
In my default layout I am setting middleware: 'auth' and in my middleware I am checking for a token and if not authenticated I am redirecting the user to the login page.
The funny thing is that when I've just set it up it worked fine but after some time (I tried to go back with my code to find the issue) I started to receive an Error Redirected when going from "/" to "/login" via a navigation guard.
I don't have any redirects but the one in the auth middleware.
What can be a problem here that I cannot see?
// middleware/auth.js
export default ({ app, error, redirect }) => {
const hasToken = !!app.$apolloHelpers.getToken()
if (!hasToken) {
error({
errorCode: 503,
message: 'You are not allowed to see this'
})
return redirect('/login')
}
}
// layouts/default.vue
<template>
<v-app dark>
<v-navigation-drawer
v-model="drawer"
:mini-variant="miniVariant"
:clipped="clipped"
fixed
app
>
<v-list>
<v-list-item
v-for="(item, i) in items"
:key="i"
:to="item.to"
router
exact
>
<v-list-item-action>
<v-icon>{{ item.icon }}</v-icon>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title v-text="item.title" />
</v-list-item-content>
</v-list-item>
</v-list>
</v-navigation-drawer>
<v-app-bar :clipped-left="clipped" fixed app>
<v-app-bar-nav-icon #click.stop="drawer = !drawer" />
<v-btn icon #click.stop="clipped = !clipped">
<v-icon>mdi-application</v-icon>
</v-btn>
<v-toolbar-title v-text="title" />
<v-spacer />
</v-app-bar>
<v-main>
<v-container>
<nuxt />
</v-container>
</v-main>
<v-footer :absolute="!fixed" app>
<span>© {{ new Date().getFullYear() }}</span>
</v-footer>
</v-app>
</template>
<script>
export default {
middleware: ['auth'],
data() {
return {
clipped: false,
drawer: true,
fixed: true,
items: [
{
icon: 'mdi-apps',
title: 'Welcome',
to: '/',
},
{
icon: 'mdi-account-group-outline',
title: 'Clients',
to: '/clients',
},
{
icon: 'mdi-briefcase-check-outline',
title: 'Orders',
to: '/orders',
},
{
icon: 'mdi-briefcase-clock-outline',
title: 'Pending Orders',
to: '/pending-orders',
},
],
miniVariant: false,
right: true,
rightDrawer: false,
title: 'Title',
}
},
}
</script>
// layouts/login.vue
<template>
<v-app dark>
<v-main>
<v-container>
<nuxt />
</v-container>
</v-main>
</v-app>
</template>
<script>
export default { }
</script>
// pages/login.vue
<template>
<div>test login</div>
</template>
<script>
export default {
}
</script>
<style>
</style>
Sorry) apparently I removed layout property from the login page component

How can I make Vuetify mobile responsive navigation bar and linked drawer have NESTED menus?

I am making a navbar component through the Vue framework using Vuetify. I would like to make the products item have a drop down into two links.
This is the template html and script code (I have some additional custom CSS for color and such that I am not adding here):
<template>
<div>
<v-toolbar id="navbar" dense elevation=1 dark >
<v-app-bar-nav-icon class="hidden-md-and-up" #click="sidebar = !sidebar"></v-app-bar-nav-icon>
<v-navigation-drawer v-model="sidebar" app hide-overlay temporary>
<v-list>
<v-list-item v-for="(item, i) in menuItems" exact :key="i" :to="item.path">{{item.title}}</v-list-item>
</v-list>
</v-navigation-drawer>
<v-toolbar-items d-flex>
<v-btn href="#" id="logo" flat depressed text>Company Name</v-btn>
</v-toolbar-items>
<v-spacer></v-spacer>
<v-toolbar-items class="hidden-sm-and-down">
<v-btn text v-for="item in menuItems" :key="item.title">
<router-link :to="item.path">{{item.title}}</router-link>
</v-btn>
</v-toolbar-items>
</v-toolbar>
</div>
</template>
<script>
export default {
data: function() {
return {
sidebar: false,
menuItems: [
{ path: "/product", name: "product", title: "Product" },
{ path: "/us", name: "us", title: "Us" },
{ path: "resources", name: "resources", title: "Resources" },
{ path: "/portal", name: "login", title: "Login" }
]
};
}
};
</script>
How about app-bar?
v-menu tag support drop down
https://vuetifyjs.com/en/components/app-bars/#dense

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>

Dynamic Buttons in Navigation Bar using Vuetify

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