I'm working on a web application using Vue 2 as the framework and the accompanying Vue Router for routing purposes.
I'm developing a kind of tabbed view, so my current approach is to define child routes for my main component. Something along the lines of:
{ path: '/user/:id', component: User, children: [
{ path: '', component: UserHome },
{ path: 'profile', component: UserProfile },
{ path: 'posts', component: UserPosts }
]}
The setup is OK and routing works as expected. I'm now looking into defining links from the User component's template to its children (the tabbed navigation). I'm also looking to define a link from the UserHome component directly to its sibling components (UserProfile& UserDetails).
As far as I can tell there's no easy way to avoid repeating the full path in the toattribute of the router-link component to avoid breaking the navigation, see this working Fiddle & this broken Fiddle and notice the values of the to attributes. I would expect to be able to define a relative path as the value of the to attribute to navigate between child and/or sibling paths.
Does anyone know if there's a better way to avoid repeating full navigation paths in a router-link component?
Related
Routes for my Module:
const routes: Routes = [
{ path: ":level1/:level2/:level3", component: CategoriesComponent },
{ path: ":level1/:level2", component: CategoriesComponent},
{ path: ":level1", component: CategoriesComponent},
{ path: "", component: CategoriesComponent },
];
the Categories component Generates some links like so:
<a [routerLink]="['category1']" [relativeTo]="activatedRoute">My Link</a>
the ngOnInit & ngOnDestroy are called each time it navigates between those routes.
What I need is the component to stay mounted and not re-init each time.
Stackblitz link to illustrate the difference between using QueryParameters and RouteParameters: Angular example
NOTE: Dont suggest RouteReuseStrategy: that isn't the answer we are looking for. I have another angular application that doesn't reload the component between routes. And this is the official expected behaviour.
You need to dive into a RouteReuseStrategy and create your custom strategy with saving touched pages
Docs
RouteReuseStrategy allows you to tell Angular not to destroy a component, but in fact to save it for re-rendering at a later date. https://stackoverflow.com/a/41515648/15439733
I have something like:
const routes: Routes = [
{
path: ':path', component: SiteRoot, children: [
{ path: '', loadChildren: '../modules/maple/template.module#TemplateModule' }
]
}
];
I wish to use this :path url to match multiple module dynamically. each module have there own internal Route.
Is there any way I can achieve this?
I tried ViewContainerRef with ResolveComponentFactory but it does not work with module only component. Event with NgModuleFactoryLoader, Routes cannot be applied.
EDIT, to make everything clear:
What I am trying to achieve is to have different module display on same route path. For example user can see user dashboard at "home" path, and admin can see admin dashboard at "home" path as well.
This feature is defined by business logic, so, I cannot change admin dashboard to another url
I think you are trying to create your routing module incorrectly. Anyway, you should write why you need this. I'll try to answer. Every module should have it's own path, so routing module should be strict and static. If you trying it for security, use guards and hide item from menu component.
If you need URLs like this: "/username1/profile", "/username2/profile" you can simply use code like yours, or use lazy loading. create routing file for parent module:
{ path: ':username', loadChildren: '../users/user.module#UserModule' }
Than create routing file for child module:
{ path: '', loadChildren: 'UserComponent', children: [
{ path: '', redirectTo: 'profile' },
{ path: 'profile', component: ProfileComponent}
]
}
Updated By your case:
by your case you can change your HTML file. For example in app.component.html if your code is:
<div>
<router-outlet></router-outlet>
</div>
You can change it with:
<div *ngIf="isLoggedIn | async">
<admin-panel></admin-panel>
</div>
<div *ngIf="(!isLoggedIn | async)">
<router-outlet></router-outlet>
</div>
I have 2 route components:
1) A people product list component 2) A product detail component
The list shows the products and then there is a router-link to that product using history in the router definition/scope.
What I am trying to achieve is to get the data from the parent list routes into the child detail product template.
So I am working with vuex as I am storing the data in the store method. Below is the gist example with the setup I have got.
https://gist.github.com/mdunbavan/5cb756ff60e5c5efd4e5cd332dcffc04
The PeopleListing component works well and when clicking the router link it goes to the correct url and the data in the vue debug looks okay for vuex as below:
state:Object
currentProduct:undefined
products:Array[0]
route:Object
from:Object
fullPath:"/products/copy-of-long-shirt-dress-tudor"
hash:""
meta:Object (empty)
name:"product"
params:Object
path:"/products/copy-of-long-shirt-dress-tudor"
query:Object (empty)
What I am trying to do is basically render the data so it shows the router data within the homepage still and not look like it is going to another page which is what it is doing at the moment. The journey I am looking to create is as follows:
1) index page renders the PeopleListing
2) when clicking the it opens some animation within that template
3) the animation then renders the data from that clicked route such as '/products/the-product-title'
On point 3) we have to try and get all data attributes from that object.
Is it possible with the setup that I have got in my gist?
Thanks in advance!!
'product/:handle' is a child route for the '/' route, as you want to nest them.
Your router should look like this.
As you want to pass data to your route using params.
When props is set to true, the route.params will be set as the component props.
const router = new VueRouter({
mode: 'history',
routes: [
{ path: '/', component: PeopleListing,
children: [
{ name: 'product', path: '/products/:handle', component: ProductDetail, props: true }
]
},
]
});
I'm confused about how and when you can use getChildRoutes because it's part of PlainRoute. How do you access PlainRoute in the first place? So instead of building <Route> components I can use <PlainRoute>s and then inside the component it was rendering it will have getChildRoutes? What does partialNextState refer to?
Plain routes are ordinary JavaScript objects, and can be used in <Router> like so:
const routes = {
path: '/',
component: App,
indexRoute: {
component: Home,
},
childRoutes: [
{ path: 'page1', component: Page1 },
{
path: 'page2',
component: SomeWrapper,
childRoutes: [
{ path: 'subpage1', component: Subpage1 },
],
},
],
};
ReactDOM.render(<Router history={ browserHistory } routes={ routes }/>, document.body);
That is, the indexRoute - if present - corresponds to adding an <IndexRoute> as a child of a <Route>, and childRoutes corresponds to adding child <Route>s. They both accept the same attributes as the corresponding JSX tags accept props.
Plain routes are useful for example for splitting your route definition up in multiple files. In a large app, it may be useful to decouple pages from their exact location in the route hierarchy, and build the route hierarchy up by importing childRoutes to immediate parent modules instead of having the entire route hierarchy hardcoded into the root module. It is also easy to build reusable navigation components like tab containers and breadcrumbs if you use plain routes, as the routes themselves can then be sent as props defining the links those components should include.
getChildRoutes and getIndexRoute are asynchronous variants of the childRoutes and indexRoute attributes, and allow for dynamic routing and code splitting. For example, you could for fun make getChildRoutes refer to itself recursively. I don't know what partialNextState is supposed to be, and I've never needed to use it.
I have a scenario where the first segment in the url will be a unique identifier. That unique identifier will be used in main routes and in the child routes as well.
Here is how i have defined my routes config
export const routes:RouterConfig = [{
path: ':academy_url',
children: [
{path: '', component: CoursesComponent},
{path: 'courses',
children: [
{path: '', component: CoursesComponent}
]
}
}
];
:academy_url is the param i plan on using in the child components. I can access this param in the child components (CoursesComponent for example), but i do not have for some reason access to it in the main app component.
The params array is empty in the main component when i try observables as well as snapshot.How do i access this param in app component? Right now i have a workaround which depends on a service emitting the param value from child components, but that is very inconvenient as this happens every time a component loads or page refreshed.
I need a more direct approach and i feel that it's either a bug or maybe the main app component is not supposed to have access to entry level params?
Also, i tried to create a plunker but i'm not sure how i make it work in there as it gives me undefined route error for it's plunker url key.