How can i pass active class through $router.push in Vue.js - vuejs2

I am using router-link for menu list. With that, active class is adding properly on clicking the link. I have a button in a page and it will navigate to another page using $router.push function but the active class is not removed from the previous page link and it is not added to navigated page.
btnClick: function () {
this.$router.push({ path: '/NextPage' })
},
Can i force set active class through this.$router.push() function?

Add linkActiveClass option while creating router object.
For e.g
const router = new VueRouter({
linkActiveClass: 'active'
});
linkActiveClass is one of the route options.
https://router.vuejs.org/api/#name

Related

Vue URL Updating but Component is not

Having an issue with my url updating but the page not.
From the home page, I display a list of projects. Clicking a project will take you to "website.com/project/project-1" and everything works as intended.
However, at the bottom of that page, I again show a list. This list is the same as homepage, with same functionality. But the problem is, is that it will update the url to "website.com/project/project-2" but the page will not re-render or change.
An example of my code
My current router-path of the component.
path: '/project/:project_slug',
name: 'ProjectPage',
component: ProjectPage
My Router Link from the project page to the new project page
<router-link :to="{ name: 'ProjectPage', params: {project_slug: projectHighlightSlug} }">
<h4 class="header-17 semibold">{{projectTitle}}</h4>
</router-link>
Update
This is my current method/watch section
methods: {
goToProject() {
this.$router.push({
name: 'ProjectPage',
params: {project_slug: this.projectHighlightSlug}
})
},
},
watch:{
// eslint-disable-next-line no-unused-vars
'$route'(to, from) {
this.goToProject();
}
}
However, the to,from is "defined but never used" and clicking my button to call goToProject() gives me the error;
"You may have an infinite update loop in watcher with expression "$route""
As explained in the Vue Router docs, when the url the user navigates to uses the same component, it uses the same instance of that component. The docs therefore recommend to listen to $route changes or to use the beforeRouteUpdate navigation guard.
You need to watch the routes to update your page. see code below
watch:{
'$route' (to, from) {
this.goToProject()
// call your method here that updates your page
}
},
source dynamic route matching

Vuejs component reuse on navigation change - clarification sought

In the following example, if the user navigates from /user/foo to /another_page and then to /user/bar, will the User component be reused?
const User = {
template: '<div>User</div>'
}
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User }
]
})
The Vue Router manuals says ...
One thing to note when using routes with params is that when the user navigates from /user/foo to /user/bar, the same component instance will be reused. Since both routes render the same component, this is more efficient than destroying the old instance and then creating a new one. However, this also means that the lifecycle hooks of the component will not be called.
Dynamic Route Matching
... but it's not clear whether the component is only reused when there are no intermediary navigation steps. Is there any documentation that discusses component reuse in this kind of detail?
Thanks!
If you navigate from /user/foo to /user/bar then the component will be reused.
This is often used when displaying product page for example. Note that there are ways to rebuild component if it is needed.
If you will navigate from /user/foo to /another_page and then navigate to /user/bar then your component will be destroyed when leaving to /another_page and created when navigating to /user/bar.
To sum up:
/user/foo -> /another_page - component gets destroyed
/user/foo -> /user/bar - component will be reused

why parent component never render until child router is complete?

In my vue application I have route inside route. the problem is until the inner route is resolved then the outer/parent route is display.
Here is how I defined the routes:
const router = new VueRouter({
// Use the HTML5 History API (fallback to URL hash if unsupported)
mode: "history",
routes: [
{
path: "/",
name: "base",
component: Base,
children: [{ path: "", name: "home", component: Home }]
}
]
});
The problem is vue is waiting for beforeRouteEnter to complete then it show the Home and Base.
If I remove the next() from beforeRouterEnter in the Home the component base is never display.
This is a problem because Home can take a lot of time to load data meanwhile base should be render to screen (base has toolbar for example).
Here is example of the problem
How can I solve this issue?
Sometimes you need to fetch data from the server when a route is
activated. We can achieve this in two different ways:
Fetching After Navigation: perform the navigation first, and fetch
data in the incoming component's lifecycle hook. Display a loading
state while data is being fetched.
Fetching Before Navigation: Fetch data before navigation in the
route enter guard, and perform the navigation after data has been
fetched.
Since your fetch takes too much time, your preferable approach would be the first aforementioned. Jest perform your API calls in mounted/created hooks of Home.vue component.

Element UI NavMenu gets out of sync with current route

I'm using the Element UI NavMenu with :router="true". It is working fine when I click on menu links (route changes and active menu item changes). The issue I'm having is that when I click on the browser navigation buttons (back and forward), the route and component change, but the NavMenu active tab does not change.
Is there an easy way to make sure the NavMenu and current route stay in sync with each other when using the browser navigation buttons? I'm using vue-router with mode: 'history'. I would have thought that this would be handled automatically.
I originally tried to implement this answer with no luck. I now have a working solution for this issue. In my navigation component, I have an el-menu with :router="true" and:default-active="activeLink"`.
Since I have a fairly simple Vue application, I did not want to loop over my router paths and build the NavMenu dynamically. This is a good practice, but I wanted to understand how it works at a basic level first.
From the element-ui docs, default-active controls the index of currently active menu. I added activeLink as a data property:
data() {
return {
logo: logo,
activeLink: null,
}
},
and then added a watch property as described in the gist linked above:
watch: {
$route (to, from) {
this.activeLink = to.path;
}
},
The part I was missing was that the index and the route properties of the el-menu-item need to be the same. Also, we can add a mounted method to make sure that the correct nav link is made active no matter what path we load the app from:
mounted: function(){
this.activeLink = this.$route.path;
},
That fixed the issue of the NavMenu getting out of sync when I use browser navigation buttons.
This was a pain to get to work. I couldn't get beforeRouteUpdate() to work at all, and :default-active="$route.path" almost works, but not if you have parameters for your routes. My current solution is to name all of my routes, and add menu items where the index is the name. Then the default-active value can just be taken from $route.name.
<el-menu :default-active="$route.name" #select="menuSelect">
<el-menu-item index="summary">
<span slot="title">Summary</span>
</el-menu-item>
<el-menu-item index="memory">
<span slot="title">Memory Overview</span>
</el-menu-item>
...
</el-menu>
And in your component:
public menuSelect(index: string) {
this.$router.push({
name: index,
});
}
You can also avoid the annoying error Navigating to current location ("summary") is not allowed like this:
public menuSelect(index: string) {
if (this.$route.name !== index) {
this.$router.push({
name: index,
});
}
}

Declarative router link not clearing model in Vue component using VueRouter

Developing a task scheduler the path '/task?id=10' fills the component model with an async response with the task information, that works ok.
In the navigation bar I have the following router link:
<router-link to="/task">New Task</router-link>
So I am using the same path and component for creating a new task and editing existing ones all based in if "id" parameter is present or not.
The problem is that if I am in path '/task?id=10' and I fill some model fields, then I click the router-link pointing to '/task' (no params) it changes the browser URL but it does not clear the component model so the input data persists.
How can I restart/reload the component when landing it through a declarative router-link?
You can make parent-child component. Parent component is on /task route, child would be on '/task/10. More, Nested Routes. Also, you don't need to append '?id=', just /task/10.
const router = new VueRouter({
routes: [
{ path: '/task', component: Task,
children: [
{ path: ':id', component: TaskId }
]
}]
});
jsfiddle