vue-router
vue-router copied to clipboard
linkActiveClass isn't set on original link when visiting through alias
Vue.js & vue-router.js version
2.5.17 & 3.0.1
Reproduction Link
https://jsfiddle.net/8xrk1n9f/1279/
Steps to reproduce
router.map({
'/foo': {
component: Foo
},
'/bar': {
component: Bar
}
})
router.alias({
'/baz': '/bar'
})
What is Expected?
The /baz
path is alias of /bar
, it should be active when i click /baz
link.
What is actually happening?
nothing happened, but route to component Bar
Any progress on this?
This went under my radar for too long. I will take a look tomorrow
Forgot to give an update. The current mechanism to compare route doesn't properly take into account aliases as it should compare records. There is a workaround to do it in userland but this depends on #2286 being merged
There is a workaround to do it in userland
@posva you mind sharing some example/links ?
It depends on that PR to be merged first
Any progress?
I know it's probably not the most straightforward way to implement it but i have a workaround that might help some people here.
{
{
path: '/',
beforeEnter: (to, from, next) => next('/actual-route'),
},
{
path: '/actual-route',
},
}
This wil redirect your alias to the intended route and setting the linkActivelass when visiting through an alias.
(source: https://github.com/vuejs/vue-router/issues/1191)
Any updates on the PR merge or other fix?
Not clear if the above comment means this is fixed? Just hit it today, really can't use the alias feature without correct link highlighting. When is 4.x planned for release?
Is there any update on planned date for 4.x release?
The release was one month ago.
https://github.com/vuejs/vue-router-next/releases/tag/v4.0.0
That's for Vue 3 though.
You could probably do something I have done myself in other scenario.
In my case
- I did not want the redirect to occur
- routes should have different parameters
The actual use case is - you might want to have a page for viewing a list of something, another page for creation/editing and one for viewing a single something:
-
/users
- this page does not need an ID -
/users/1/edit
- no NavLink for this route -
/users/1/view
- no NavLink for this route
From the example - the list of users does not need an ID. However I still wanted the active class to shown on the other two pages..
Copy-paste my answer from: https://stackoverflow.com/a/69933108/1215913
using vuejs 3
in main app.vue
I have routes defined. The routes are then parameter-injected into sidemenu component
(which is not important in this example)
app.vue
dependencies
import { ref, watch } from "vue";
import { useRoute } from "vue-router";
setup()
method (using composition API
):
setup() {
const route = useRoute();
const myActiveClass = ref(null);
const checkIfMustActivateRoute = () => {
return {
active:
window.location.pathname.startsWith("/users/view/") ||
window.location.pathname.startsWith("/users/edit/"),
};
};
watch(
() => route.fullPath,
async (_) => {
myActiveClass.value = checkIfMustActivateRoute();
}
);
myActiveClass.value = checkIfMustActivateRoute();
const routes = ref([
{ id: 0, name: "Home", href: "/", icon: "fas fa-home" },
{
id: 1,
name: "Users",
href: "/users",
icon: "far fa-clone",
class: myActiveClass,
},
]);
return {
routes,
};
},
NavLink
s are dynamically generated like so:
<li v-for="tab of routes" :key="tab.id" class="nav-item">
<router-link :to="tab.href" class="nav-link" :class="tab.class">
<div class="align-items-center">
<span class="nav-link-icon"><i :class="tab.icon"></i></span>
<span class="nav-link-text ms-3">{{ tab.name }}</span>
</div>
</router-link>
</li>
Now whenever the router's path property changes I trigger the active class update function. This way we don't have to use aliases or any other trickery.
The result is - for all 3 paths I always enable active
class.
Copy-paste END
Now, given that I just started learning JavaScript I suppose there could be some issues here :)