Vue-router v4: Nested route not matching with parent route - vue.js

In this project I'm using Vue 3 (vite) and Vue-router v4 and trying to make routing work correctly.
I am trying to navigate to /escape-rooms/my-escape-room but the <router-link> object inside my menu does not get the class .router-link-active. In the main route /escape-rooms it does. I'm not sure what I'm doing wrong because the documentation states that nested routes automatically 'activate' any parent links with this class.
I have this list of routes:
const routes = [
{path: '/', name: 'main', component: Home},
{path: '/escape-rooms', name: 'escape-rooms', component: EscapeRooms},
{path: '/escape-rooms/:urlName', name: 'escape-room-item', component: EscapeRooms, props: true},
{path: '/contact', name: 'contact', component: Contact}
]
This is de part of my menu layout:
<div class="menu">
<div class="menuitem">
<router-link to="/contact">
contact
</router-link>
</div>
<div class="menuitem">
<router-link to="/escape-rooms">
escape-rooms
</router-link>
</div>
</div>

For anyone stumbling on the same issue. follow this article: https://github.com/vuejs/rfcs/blob/master/active-rfcs/0028-router-active-link.md#unrelated-but-similiar-routes

Related

Vue Router Child showing

I'm trying to make a router with Vue, it works very well, but there is a point in my mind.
Component Child is loaded with "click" at the start of vue, but,
In the Address Bar
When I type "http://127.0.0.1:8000/contact/new" it is displayed that the main component is not started. what is the reason for this?
app.vue
<template>
<router-link :to="{ name: 'home'}">Home</router-link>
<router-link :to="{ name: 'contact'}">Contact</router-link>
<div>
<router-view/>
</div>
</template>
contact.vue
<template>
<div>
Contact Page
<router-link :to="{ name: 'contactNew'}">New Add Contact</router-link>
<div>
<router-view/>
</div>
</div>
</template>
contactAdd.vue
<template>
<div>
Contact New Add
</div>
</template>
router
import Contact from "../Views/contact/Contact.vue";
import Home from "../Views/Home.vue";
import ContactNew from "../Views/contact/ContactNew.vue";
export default [
{
path: '/home',
component: Home,
name: 'home',
},
{
path: '/contact',
component: Contact,
name: 'contact',
children: [
{
path: 'new',
component: ContactNew,
name: 'contactNew',
},
]
},
{
path: '/:pathMatch(.*)*',
redirect: '/home',
}
];

What would be the best way to use vue routes?

I'm a bit new to Vue routes. I have a table in Home.vue and each row has a button in order to go to the details. I'll try to explain what I imagine. I want the redirection to open a new screen Overview with a sidebar that has 3 options: Overview, Commits and Files. My problem is to understand what should be the parent and what should the child. I'm sure that Commits and Files are children but should Overview be also a child or the parent of Commits and Files? The row that redirects to details:
<router-link :to="{ 'name': 'details', 'params': { 'tool': tool } }">{{id}}</router-link>
The routes that I currently have:
const DetailsChildren = [
{
path: 'commits/:tool',
name: 'commits',
component: commits
},
{
path: 'files/:tool',
name: 'files',
component: files
}
];
export default new Router({
routes: [
{
path: '/',
name: 'home',
component: Home
}
{
path: '/overview/:tool',
name: 'details',
component: details,
children: DetailsChildren
}
],
mode: 'history'
});
And DetailsChildren is as follows:
<template>
<div class="main">
<sidebar />
<router-view />
</div>
</template>
Currently DetailsChildren is Overview. But I think DetailsChildren should be the parent of Overview, Files and Commits and then I need to create another component Overview. But then I have two problems. First one is how I load Overview when I move from the table to DetailsChildren? The second one is that I want the route to be /overview/:tool. I'm a bit confused. What would be best way to handle the routes in this situation?
What you want to do is have three children under your details route, each with their own absolute path from /.
const DetailsChildren = [
{
path: '/overview/:tool',
name: 'overview',
component: overview
},
{
path: '/commits/:tool',
name: 'commits',
component: commits
},
{
path: '/files/:tool',
name: 'files',
component: files
}
];
This will create the following path mappings
/overview/:tool
Top-level component: details
Child component: overview
/commits/:tool
Top-level component: details
Child component: commits
/files/:tool
Top-level component: details
Child component: files
See the guide on Nested Routes.
You may think you can use an empty path for the overview route but this would then require the URL to have a trailing slash (ie /overview/tool/) and I figured you don't want that.
It's also recommended to remove the name from your details route and instead, link to the default child route (ie overview). Eg
<router-link :to="{ name: 'overview', params: { tool } }">{{id}}</router-link>
Otherwise, the router gets confused about which to display, the parent (empty) or child.
Your sidebar links can simply use the child route names to create their links, eg
<nav>
<ul>
<li>
<router-link :to="{name: 'overview'}">Overview</router-link>
</li>
<li>
<router-link :to="{name: 'commits'}">Commits</router-link>
</li>
<li>
<router-link :to="{name: 'files'}">Files</router-link>
</li>
</ul>
</nav>

Router Link only updates active class once

I am trying to use <b-nav-item> tags as router links but the active link class only updates one time – I can load the page and click on a nav item and the class changes appropriately. But clicking again does not.
I have tried various syntax for the link attributes including:
to="dashboard"
to="/dashboard"
:to="{ name: 'Dashboard' }"
:to="{ path: '/dashboard' }"
I've also tried adding the exact attribute tag. Nothing is working and I feel like I'm running in circles here. Any ideas?
CompanionNavigation:
<template>
<div>
<b-nav pills>
<b-nav-item :to="{ name: 'Dashboard'}" exact>Dashboard</b-nav-item>
<b-nav-item :to="{ name: 'Contacts' }" exact>Contacts</b-nav-item>
</b-nav>
</div>
</template>
Routes:
{
path: '/dashboard',
name: 'Dashboard',
component: Dashboard,
},
{
path: '/contacts',
name: 'Contacts',
component: Contacts,
},
This was resolved by removing the following from my main template file:
<!-- Load Vue followed by BootstrapVue -->
<script src="//unpkg.com/vue#latest/dist/vue.min.js"></script>
<script src="//unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.min.js"></script>

Vue Child is not loaded after route enter

This is my router structure
{
path: '/',
name: 'home',
component: Home
},
{
path: '/user/:id',
name: 'user',
component: User,
children: [
{
path: '',
name: 'page',
component: Page
},
.....
}
I used this in Home.vue to redirect (/user/12345)
<router-link
:to="{
name: 'user',
params: {id: user.userId}
}"
>
When I clicked this link in home page, it routes correct path however I can not render child component (Page.vue) However when I reload the page, child component is loaded successfully. (url is still same)
There is an only rendering issue when I click the link on the homepage. How can I get rid of this. Thanks in advance.
User.vue
<template>
<div>
<NavDrawer/>
<router-view></router-view>
</div>
</template>
Edit: Any help will be so beneficial for me. Thanks

Make the first child route as the active class whenever the sub-route path is an empty path

I have a Main Navigation nav bar with some links. In the home page, i.e., in the root path ('/'), I have nested (child) routes.
Route configration:
const routes = [
{path: '/', component: HomeMainContent, children: [
{path: '', component: MovieList},
{path: 'in-theaters', component: MovieList},
{path: 'coming-soon', component: ComingSoonList},
{path: 'trailers', component: TrailerList},
]},
{path: '/about', component: About},
{path: '/contact',component: Contact},
];
So when the root path ('/') is active, its child router root path ('') is activated.
The template of child component router is in this way:
<template>
<div id="homeSubMenuWrapper">
<ul id="subMenuList">
<li v-for="menu in menuList">
<router-link class="menuItem" :to="menu.path">{{menu.name}}</router-link>
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
menuList: [
{name: 'IN THEATER', path: '/in-theaters'},
{name: 'COMING SOON', path: '/coming-soon'},
{name: 'TRAILERS', path: '/trailers'},
]
}
}
}
</script>
Since, both the path ('') and ('in-theaters') have the same component, I would like to make the router-link of path ('in-theaters') to have the class of router-link-active whenever the child path ('') of its parent path ('/') is active. How can I do that?
Meaning the first child route ('in-theaters') should have the active class whenever the sub-route path is an empty path ('').
With #Potray's advice, I ended up checking the $route.path and the child path inside the template.
<template>
<div id="homeSubMenuWrapper">
<ul id="subMenuList">
<li v-for="menu in menuList">
<router-link :class="[$route.fullPath ==='/' && menu.path === '/in-theaters' ? 'menuItem router-link-active' : 'menuItem']" :to="menu.path">{{menu.name}}</router-link>
</li>
</ul>
</div>
</template>