vuetify and vue-router active navbar for multiple tabs - vue.js

I would like to achieve highlighting the same menu in a navbar while browsing different tabs.
As seen on the image above, belong is selected while on the department tab. I still wanted to highlight the belong menu while selecting the selection tab. Please see my code below.
Navbar component
<v-list dense>
<v-list-item v-for="item in items" :to="item.to" :key="item.title" link>
<v-list-item-icon>
<v-icon>{{ item.icon }}</v-icon>
</v-list-item-icon>
<v-list-item-content>
<v-list-item-title>{{ item.title }}</v-list-item-title>
</v-list-item-content>
</v-list-item>
</v-list>
<script>
export default {
data () {
return {
drawer: true,
items: [
{ to: { name: 'dashboard'}, title: 'Dashboard', icon: 'mdi-account' },
{ to: { name: 'department'}, title: 'Department', icon: 'mdi-home-city' },
{ to: { name: 'salary'}, title: 'Salary', icon: 'mdi-cash' },
],
mini: false,
}
},
}
</script>
Router Tab Component
<template>
<v-tabs class="mb-2" mobile-break-point="200px">
<v-tab v-for="tab in navbarTabs"
:key="tab.id"
:to="tab.to"
>
{{ tab.name }}
</v-tab>
</v-tabs>
</template>
<script>
export default {
data() {
return {
navbarTabs: [
{
id: 0,
name: "Department",
to: { name: 'department' }
},
{
id: 1,
name: "Section",
to: { name: 'section' }
},
]
}
}
}
</script>
Routes.js
import Vue from 'vue';
import VueRouter from 'vue-router';
Vue.use(VueRouter);
import Dashboard from './views/Dashboard'
import Department from './views/Department'
import Section from './views/Section'
import Salary from './views/Hello'
export const router = new VueRouter({
mode: 'history',
routes: [
{ path: '/dashboard', name: 'dashboard', component: Dashboard },
{ path: '/belong/department', name: 'department', component: Department},
{ path: '/belong/section', name: 'section', component: Section },
{ path: '/salary', name: 'salary', component: Salary},
],
});
The current setup is that department path is connected to the belong menu, but I wanted to make it a dynamic wherein section tab will also set the navbar belong into active.
Both of these components are inside the App.vue (main vue file for routing)

UPDATE: I have now fixed this issue.
Here is what I did with the router.js
export const router = new VueRouter({
mode: 'history',
routes: [
{ path: '/404', component: NotFound },
{ path: '*', redirect: '/404' },
{ path: '/', redirect: '/dashboard' },
{ path: '/dashboard', name: 'dashboard', component: Dashboard },
{ path: '/org', name: 'organization', component: Organization,
children: [
{ path: 'department', name: 'department', component: Department},
{ path: 'section', name: 'section', component: Section },
{ path: 'position', name: 'position', component: Position }
],
},
{ path: '/salary', name: 'salary', component: Salary},
],
});
I created a parent component (organization) that holds all the other sub components (department, section, position) and set them as children.
If there are other best practices to do this, please feel free to share your knowledge.

Related

VueRouter send child components to parent RouterView based on name

I have this template for my Routing:
<template>
<article>
<router-view name="modal" />
<div class="l-app-container">
<router-view name="sidebar" />
<router-view name="main" class="main" />
</div>
</article>
</template>
This works fine when calling most routes:
const routes = [
{
path: "/",
name: "app",
components: {
main: AppBase, // This components content is: `<router-view name="content"></router-view>`
sidebar: Sidebar,
},
children: [
{
path: "orders",
name: "app.orders",
components: {
content: Orders,
},
},
{
path: "order",
name: "app.order",
components: {
content: Order,
},
children: [
{
path: "details",
name: "app.order.details",
components: {
tab: OrderDetails,
},
},
{
path: "create",
name: "app.order.create",
components: {
modal: OrderCreate,
},
},
],
},
],
},
];
export default createRouter({
history: createWebHashHistory(),
routes,
});
The Sidebar and Main router-view are working fine when routing.
But what I want, is that when calling app.order.create, it routes the component to the <router-view name="modal" />, but it doesn't.
It expects that that router-view is inside the AppBase component. But I need it outside that 'main` router-view.
Not only because of the front-end is written that way, but also because that's more flexible for all other routes that the App has.

Navbar selects two drawers at once if one path contains the other in Vue

I'm creating an application in Vue.js with a sidebar.
In v-list-item, in the path :to="link.route", I'm using the names for routes: { name: "dashboard" }.
The problem occurs when the path to one link is contained in a link to the other path.
Eg. path: '/' (dashboard) is contained in path: '/help'.
If I click on Help, then both sidebar drawers are selected:
Template:
<template>
<div>
<v-navigation-drawer v-model="drawer">
<v-list nav dense>
<v-list-item-group>
<v-list-item
v-for="link in links"
:key="link.text"
:to="link.route">
<v-list-item-content>
<v-list-item-title class="white--text">{{
link.text
}}</v-list-item-title>
</v-list-item-content>
</v-list-item>
</v-list-item-group>
</v-list>
</v-navigation-drawer>
</div>
</template>
Script:
<script>
export default {
data: () => ({
drawer: true,
}),
computed: {
links() {
return [
{
text: "Dashboard",
route: { name: "dashboard" },
},
{
text: "Help",
route: { name: "help" },
},
];
},
},
};
</script>
Router:
import Vue from 'vue'
import VueRouter from 'vue-router'
import Dashboard from '../views/Dashboard.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'dashboard',
component: Dashboard
},
{
path: '/help',
name: 'help',
}
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
I fixed my problem by adding path { name: "dashboard", path:'/' }in dashboard route declaration.
Code before:
links() {
return [
{
text: this.$i18n.t("navbar.dashboard"),
route: { name: "dashboard"},
},
{
text: this.$t("navbar.help"),
route: { name: "help"},
},
];
},
Code after:
links() {
return [
{
text: this.$i18n.t("navbar.dashboard"),
route: { name: "dashboard", path:'/' },
},
{
text: this.$t("navbar.help"),
route: { name: "help"},
},
];
},
It's not exactly what I wanted, but it solves the problem.

Vue router id gets undefined when taken from vuex

I am trying to get the id of currently logged user from Vuex getters and pass it into the router link, but somehow it gets undefined, even though I console.log it and it shows legitimate user ID. In my template. Here I loop over an array of objects where I keep my route name:
<v-list dark class="mt-5 userList" style="background: #515151;">
<v-list-item
v-for="item in sideBar"
:key="item.title"
class="tile"
>
<router-link :to="item.route">
<span class="userIcon">
<v-list-item-icon>
<v-icon style="color: #FFA255">{{ item.icon }}</v-icon>
</v-list-item-icon>
</span>
<span class="userTitle">
<v-list-item-content>
<v-list-item-title style="color: #FFA255">
{{ item.title }}
</v-list-item-title>
</v-list-item-content>
</span>
</router-link>
</v-list-item>
</v-list>
I think this part speaks for itself My script section:
export default {
data() {
return {
userParams: null,
sideBar: [
{title: 'User', icon: 'note', component: 'UserInfo', route: `/user/${this.userParams}`},
{title: 'Rated albums', icon: 'note', component: 'Rated', route: `/user/${this.userParams}/rated`},
{title: 'Owned', icon: 'favorite', component: 'Owned', route: `/user/${this.userParams}/owned`},
{title: 'Settings', icon: 'settings', component: 'Settings', route: `/user/'${this.userParams}'/settings`},
],
}
},
computed: {
...mapGetters([
'getUserId'
])
},
created() {
this.userParams = this.getUserId;
console.log(this.userParams)
},
}
My router.js
{
path: '/user/:id',
component: User,
children: [
{
path: '/',
component: UserInfo,
name: 'userInfo'
},
{
path: 'owned',
component: Owned,
name: 'owned'
},
{
path: 'rated',
component: Rated,
name: 'rated'
},
{
path: 'settings',
component: Settings,
name: 'settings'
}
],
beforeEnter (to, from, next) {
if(authStore.state.idToken) {
next()
} else {
next('/signin')
}
}
},
Make sideBar a computed property so it is re-evaluated when getUserId changes.
I don't see a reason to keep a copy of getUserId in userParams either.
computed: {
...mapGetters([ 'getUserId' ]),
sideBar () {
const params = { id: this.getUserId } // this is reactive
return [{
title: 'User',
icon: 'note',
route: { name: 'userInfo', params }
}, {
title: 'Rated albums',
icon: 'note',
route: { name: 'rated', params }
}, {
title: 'Owned',
icon: 'favorite',
route: { name: 'owned', params }
}, {
title: 'Settings',
icon: 'settings',
route: { name: 'settings', params }
}]
}
},
At the moment, your route strings are only calculated once when your component is created

route.params has properties that don't match dynamic url

I want to ask about vue-router. This is my first time using vue js.
Initially I was on the route:
localhost: 8080 / article / edit-article / 2
and when I move to route:
localhost: 8080 / page
this is still running.
But when I moved from:
localhost: 8080 / article / edit-article / 2
to:
locahost: 8080 / dashboard
the route instead changed to:
localhost: 8080 / article / edit-article / dashboard
not:
localhost: 8080 / dashboard
This my vue-router:
export default new Router({
mode: 'history',
linkActiveClass: 'open active',
scrollBehavior: () => ({ y: 0 }),
routes: [
{
path: '/',
redirect: '/login',
name: 'Home',
component: DefaultContainer,
children: [
{
path: 'dashboard',
name: 'Dashboard',
component: Dashboard,
meta: {
requiresAuth: true
}
},
{
path: 'page',
name: 'Page',
component: Page,
meta: {
requiresAuth: true
}
},
]
},
{
path: '/article',
component: DefaultContainer,
meta: {
requiresAuth: true
},
children: [
{
path: '',
name: 'List Articles',
component: Article,
meta: {
requiresAuth: true
}
},
{
path: 'add-article',
name: 'Add Article',
component: AddArticle,
meta: {
requiresAuth: true
}
},
{
path: 'edit-article/:id',
name: 'Edit Article',
component: EditArticle,
meta: {
requiresAuth: true
}
},
]
},
{
path: '/login',
name: 'Login',
component: Login,
meta: {
requiresVisitor: true
}
},
]
})
I use navbar with js, like this:
export default {
items: [
{
name: 'Dashboard',
url: 'dashboard',
icon: 'icon-speedometer',
},
{
name: 'Article',
url: 'article',
icon: 'icon-note'
},
{
name: 'Page',
url: '/page',
icon: 'icon-layers'
},
]
}
and this my DefaultContainer:
<template>
<div class="app">
<AppHeader fixed>
<SidebarToggler class="d-lg-none" display="md" mobile />
<b-link class="navbar-brand" to="/dashboard">
<img class="navbar-brand-full" src="img/brand/logo.svg" width="89" height="25">
<img class="navbar-brand-minimized" src="img/brand/sygnet.svg" width="30" height="30>
</b-link>
<SidebarToggler class="d-md-down-none" display="lg" />
<b-navbar-nav class="ml-auto">
<DefaultHeaderDropdownAccnt/>
</b-navbar-nav>
</AppHeader>
<div class="app-body">
<AppSidebar fixed>
<SidebarHeader/>
<SidebarForm/>
<SidebarNav :navItems="nav"></SidebarNav>
<SidebarFooter/>
<SidebarMinimizer/>
</AppSidebar>
<main class="main">
<Breadcrumb :list="list"/>
<div class="container-fluid">
<router-view></router-view>
</div>
</main>
<AppAside fixed>
<!--aside-->
<DefaultAside/>
</AppAside>
</div>
<TheFooter>
<!--footer-->
<div>
<span class="ml-1">© 2019 local Incorporation. All Rights Reserved</span>
</div>
</TheFooter>
</div>
</template>
<script>
import nav from '#/_nav'
import { Header as AppHeader, SidebarToggler,` `Sidebar as AppSidebar, SidebarFooter, SidebarForm, SidebarHeader, SidebarMinimizer, SidebarNav, Aside as AppAside, AsideToggler, Footer as TheFooter, Breadcrumb } from '#coreui/vue'
import DefaultAside from './DefaultAside'
import DefaultHeaderDropdown from './DefaultHeaderDropdown'`
export default {
name: 'DefaultContainer',
components: {
AsideToggler,
AppHeader,
AppSidebar,
AppAside,
TheFooter,
Breadcrumb,
DefaultAside,
DefaultHeaderDropdown,
SidebarForm,
SidebarFooter,
SidebarToggler,
SidebarHeader,
SidebarNav,
SidebarMinimizer
},
data () {
return {
nav: nav.items
}
},
computed: {
name () {
return this.$route.name
},
list () {
return this.$route.matched.filter((route) => route.name || route.meta.label )
}
}
}
</script>
Thanks all
It seems likely that the problem is here:
url: 'dashboard',
This would appear to be a relative path. So if you are currently on the page http://localhost:8080/article/edit-article/2 it will resolve relative to that URL, giving http://localhost:8080/article/edit-article/dashboard. This isn't really anything to do with Vue router, it's just how relative URLs are resolved. You'd get exactly the same behaviour if you used an HTML link such as <a href="dashboard">.
If you start your relative URL with a / then it will omit the rest of the path:
url: '/dashboard',
This should fix your problem. This is what you've done with your /page URL, which is presumably why that works.
Personally I would use named routes instead, rather than trying to craft relative URLs. See https://router.vuejs.org/guide/essentials/named-routes.html

Vue tree navigation (pluggin) how to map routes

I have used vue-tree-navigation for implement this Tree navigation menu .
When I hit a menu item (eg :- Create item) it should route to the create item component.
But it's only print the name of the route in the navigation bar and doesn't route to any where.
http://localhost:8080/inside#item
how do I fixed this problem?
this is my routes.js file
const routes = [
{ path: "/", component: welcome },
{
path: "/inside",
component: inside,
name: inside,
children: [
{ path: "/category", component: category, name: category },
{ path: "/sub-category", component: subCategory, name: subCategory },
{ path: "/item", component: item, name: item }
]
}
];
This is my component
<template>
<div class="inside">
<div class="sideBar"><vue-tree-navigation :items="items" /></div>
<div class="content"><router-view></router-view></div>
</div>
</template>
<script>
export default {
data() {
return {
items: [
{ name: 'Item Master', route: 'inside', children: [ // /about
{ name: 'Create item category', element: 'category', },
{ name: 'Create item sub category', element: 'sub-category', },
{ name: 'Create item', element: 'item', },
]},
],
};
}
};
</script>
Try to change a bit of things in the router file, it works well for me:
The components starts in Uppercase (just a convention)
The name with ''
Delete the / in the path
Like this:
path: "inside",
component: Inside,
name: "inside",
children: [
{ path: "category", component: Category, name: 'category' },
{ path: "sub-category", component: SubCategory, name: 'subCategory' },
{ path: "item", component: Item, name: 'item' }
]
And the most important, load (if you are not doing it already) the VueRouter with:
var router = new VueRouter({
const routes = [
...
]
});
Hope it helps!