why parent component never render until child router is complete? - vue.js

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.

Related

Reset vue component context on load when different routes use same component

Using vue router, I have two routes that are mapped to the same component, and given one route i am passing in a prop as a differentiator, then conditionally rendering content based on that prop. like so.
export default {
path: '/advanced-search',
name: 'Advanced Search',
component: AdvancedSearch
}
and
export default {
path: '/create-vendor-search',
name: 'Create Vendor Search',
component: AdvancedSearch,
props: { createMode: true }
}
These exist in two different files, advanced-search.route.js and createNewVendorSearh.route.js, respectively. The problem is that both pages are linked in my nav bar, and when i go directly from one to the other, the local state and vuex state of the components don't reset. I need this to be a brand new instance of this component every time a route calls it. How can I achieve this?

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

VueJS Routing Multiple Dynamic Parameters in url

I'm trying to implement routing over an spa which was only swapping out components based on setting true/false properties on the main VUE instance. I'm using the official Vue router for VUE.JS 2
There is a component, which i routed to the following path:
{
path: '/Foe/Bar/Details/:id',
components: {
layerTop: 'barDetail',
layerMiddle: notImportant
},
props: { layerTop: true }
},
So when the user clicks on the details button my components load as expected. My problem is when I try to navigate from this route to a new one but I want to keep my named 'layerTop' router-view as currently is. Basically I dont want to change the 'layerTop' view, just the layerMiddle view.
So I was thinking my path would look something like this:
path: 'Foe/Bar/Details/:barId/Categories/:categoryId
But I don't know how to map the :barId param to the Bar component's prop, and the categoryId to the Category comp's prop.
When it is a single parameter it works just like in the example above.
I'm pretty new to Vue and the router especially, tried to find an example on the docs but couldnt. Thank you for any input.
Check out the nested routes documentation.
https://router.vuejs.org/en/essentials/nested-routes.html
routes: [
{path: "/foo/bar". component: FooBar,
children [
path: "/:id", component: FooBarDetails,
children: [
{path: "categories/:categoryid", component: Category}
]
]
}
]

How to Properly Use Vue Router beforeRouteEnter or Watch to trigger method in Single File Component?

I'm working on an app in Vue.js using Single File Components and Vue Router. I have a Search component where I need to execute a method to re-populate search results each time a user visits the route. The method executes correctly the first time the route is visited because of the "create" hook:
created: function() {
this.initializeSearch();
},
However, when the user leaves the route (to register or log into the app for instance), and returns to the Search page, I can't seem to find a way to automatically trigger this.initializeSearch() on subsequent visits.
Routes are set up in index.js like so:
import Search from './components/Search.vue';
import Login from './components/Login.vue';
import Register from './components/Register.vue';
// Vue Router Setup
Vue.use(VueRouter)
const routes = [
{ path: '/', component: Search },
{ path: '/register', component: Register },
{ path: '/login', component: Login },
{ path: '*', redirect: '/' }
]
export const router = new VueRouter({
routes
})
I gather that I should be using "watch" or "beforeRouteEnter" but I can't seem to get either to work.
I tried using "watch" like so within my Search component:
watch: {
// Call the method again if the route changes
'$route': 'initializeSearch'
}
And I can't seem to find any documentation explaining how to properly use the beforeRouteEnter callback with a single file component (the vue-router documentation isn't very clear).
Any help on this would be much appreciated.
Since you want to re-populate search results each time a user visits the route.
You can use beforeRouteEnter() in your component as below:
beforeRouteEnter (to, from, next) {
next(vm => {
// access to component's instance using `vm` .
// this is done because this navigation guard is called before the component is created.
// clear your previously populated search results.
// re-populate search results
vm.initializeSearch();
})
}
You can read more about navigation guards here
Here is the working fiddle

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