Navbar selects two drawers at once if one path contains the other in Vue - vue.js

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.

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.

how to open new link in master page in vuejs

I have navigation drawer and this nav contained number of pages ..i want to add new page that will be contain another url but open in the same page with master page...is that possible ???
fev.vue file
<template>
<v-app>
<div class="feb">
<v-card>
<div> {{ callfeb}} </div>
</v-card>
</div>
</v-app>
</template>
export default {
computed: {
callfeb(){
href = 'https://######',
target='_self'
//window.location.href = 'https://#####'
}
}
}`</script>`<style></style>``
App.vue
computed: {
items() {
return [
{
icon: 'link',
text: i18n.t('H-D'),
path: '/feb',
perms: 'read:feb',
show: true
},
]
}
router.ts
router [
{
path: '/feb',
name: 'feb',
props: route => ({
query: route.query,
isKiosk: route.query.kiosk,
hash: route.hash
}),
component: () =>
import(/* webpackChunkName: 'user' */ './views/feb.vue'),
meta: { title: 'feb', requiresAuth: true }
},
]
the above codes are working and open the url in same page but the master content will not show. I want the url will open in the same page with master content

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

vuetify and vue-router active navbar for multiple tabs

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.

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