VueRouter send child components to parent RouterView based on name - vue.js

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.

Related

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.

Hide sidebar component some page in VUE.js

I am working with Vue.js and I have a question.
Is there a way to hide sidebar component only some page ?
This is my code below.
router.js
const routes = [
{
path: '/',
redirect: '/home',
component: () => import('#/layout/MainLayout'),
children: [
{
path: 'home',
name: 'Home',
component: () => import('Views/Home.vue'),
},
],
},
{
path: '/subpage',
redirect: '/subpage/subpage',
component: () => import('#/layout/MainLayout'),
children: [
{
path: 'subpage',
name: 'Subpage',
component: () => import('Views/Subpage/Subpage.vue'),
},
],
},
];
MainLayout.vue
<template>
<div id="content" class="content">
<router-view></router-view>
<Sidebar></Sidebar>
</div>
</template>
<script>
import Sidebar from '#/components/Sidebar.vue';
export default {
components: {
Sidebar,
},
};
</script>
Do I need to make another layout? like MainLayout2.vue
Please help.
You can add meta information to vue routes. Add the sidebar key to the routes you want to hide
{
path: '/subpage',
redirect: '/subpage/subpage',
component: () => import('#/layout/MainLayout'),
children: [
{
path: 'subpage',
name: 'Subpage',
meta:{sidebar:false}
component: () => import('Views/Subpage/Subpage.vue'),
},
],
},
Then in your layout component, make a computed property to check if the current route needs to hide the sidebar
computed:{
shouldShowSidebar(){
return this.$route.meta.sidebar!==false;
}
}
Then use this computed property to conditionally hide the sidebar on specific routes
<Sidebar v-if="shouldShowSidebar"></Sidebar>
You can add meta:{sidebar:false} to any route you want the sidebar to be hidden on

Component doesn't load while the route changes

I want to create a nested route with its children's route.
Basically what I want is,
https://localhost/contact render the ContactList component.
https://localhost/contact/add render the ContactAdd component.
What I have tried is:
let Layout = {
template: '<div>Layout Page <router-view></router-view></div>'
};
let Home = {
template: '<div>this is the home page. Go to <router-link to="/contact">contact</router-link> </div>'
};
let ContactList = {
template: '<div>this is contact list, click <router-link to="/contact/add">here</router-link> here to add contact</div>'
};
let ContactAdd = {
template: '<div>Contact Add</div>'
}
let router = new VueRouter({
routes: [{
path: '/',
redirect: 'home',
component: Layout,
children: [{
path: 'home',
component: Home
},
{
path: 'contact',
component: ContactList,
children: [{
path: 'add',
component: ContactAdd
}]
},
]
}]
});
new Vue({
el: '#app',
components: {
'App': {
template: '<div><router-view></router-view></div>'
},
},
router
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://unpkg.com/vue-router#3.0.1/dist/vue-router.js"></script>
<section id="app">
<app></app>
</section>
Here, the problem is when I change the route from /client to /client/add, the view doesn't render. What is the problem with the nested children's route here? How to solve this issue?
I check this documentation https://router.vuejs.org/guide/essentials/nested-routes.html, but It didn't help in this case.
You need to add one <router-view> in the template of <ContactList> to load its children route.
Or if you'd like to display ContactAdd in Layout, moves ContactAdd to direct child of path=/.
let Layout = {
template: '<div>Layout Page <router-view></router-view></div>'
};
let Home = {
template: '<div>this is the home page. Go to <router-link to="/contact">contact</router-link> </div>'
};
let ContactList = {
// add <router-view> in order to load children route of path='/contact'
template: '<div>this is contact list, click <router-link to="/contact/add">Add Contact In sub Router-View</router-link> here to add contact<p><router-view></router-view></p> Or Click <router-link to="/addcontact">Add Contact In Current Router-View</router-link></div>'
};
let ContactAdd = {
template: '<div>Contact Add</div>'
}
let router = new VueRouter({
routes: [{
path: '/',
redirect: 'home',
component: Layout,
children: [{
path: 'home',
component: Home
},
{
path: 'contact',
component: ContactList,
children: [{
path: 'add',
component: ContactAdd
}]
},
{
path: 'addcontact', // or move ContactAdd as direct child route of path=`/`
component: ContactAdd,
}
]
}]
});
new Vue({
el: '#app',
components: {
'App': {
template: '<div><router-view></router-view></div>'
},
},
router
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://unpkg.com/vue-router#3.0.1/dist/vue-router.js"></script>
<section id="app">
<app></app>
</section>

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