问题
I have an application where I want to show the same set of components / routes in multiple places in the application. Think something like multiple panels or side bars where the user can show the same components in multiple locations depending upon what they select.
For example the user may want to "show the status component in side panel" or "show the status component in bottom right panel on page".
(In my case the number of outlets is fixed, but the same concept could be used for a dashboard style UI with a dynamic number of cards that each have a route for the component to load)
My idea was to use the angular router with named outlets for this. That would allow for easy reuse of components supporting dynamic creation as well as keeping the current routing state in the URL for easy reloading.
So for example a url may look like:
https://.../app(side:status_comp//popup:other_comp)
I have named outlets working, but what I can't figure out how to do is to reuse a route across multiple named outlets without duplicating the route in the router config.
For example:
const appRoutes: Routes = [
{ path: 'main', component: AppComponent },
// ==> Have to repeat each route for each outlet name
{ path: 'comp_a', component: CompA, outlet: 'first' },
{ path: 'comp_b', component: CompB, outlet: 'first' },
{ path: 'comp_a', component: CompA, outlet: 'second' },
{ path: 'comp_b', component: CompB, outlet: 'second' },
// ==> Would like to just do this
/*
{ path: 'comp_a', component: CompA},
{ path: 'comp_b', component: CompB},
*/
{ path: '', redirectTo: '/main', pathMatch: 'full' },
{ path: '**', redirectTo: '/main' }
];
Simplified Template:
<p>Outlet 1</p>
<a [routerLink]="[{ outlets: { first: ['comp_a'] } }]">Comp A</a>
<a [routerLink]="[{ outlets: { first: ['comp_b'] } }]">Comp B</a>
<div class="outlet-wrapper">
<router-outlet name="first"></router-outlet>
</div>
<p>Outlet 2</p>
<a [routerLink]="[{ outlets: { second: ['comp_a'] } }]">Comp A</a>
<a [routerLink]="[{ outlets: { second: ['comp_b'] } }]">Comp B</a>
<div class="outlet-wrapper">
<router-outlet name="second"></router-outlet>
</div>
Then route the component into the outlet using:
this.router.navigate([{outlets: {first: ['comp_a']}}]);
What I would like is to just set the router with a single route to the given component and then be able to call router.navigate
with any defined route but tell it to load that route in the named outlet.
Is there any way to do this.
Here is a sample on stackblitz where I have everything setup. ng-router-reuse app
The change I want to make is shown above and in the same in the route definitions.
Any ideas?
Note: I know I could use something like Portals from the Angular CDK and dynamically load the components. The problem with that though is that the state of what the user is seeing doesn't get stored into the URL to manage by the router and it also prevents the use of router lazy loading.
回答1:
It looks like you can update router configs dynamically at runtime, at the time of navigation. Here is an example. https://stackblitz.com/edit/ng-router-reuse-c7j96a
And here is a brief explanation.
1) On link or button click find the route in the router config.
let route = this.router.config.filter(r => r.path === 'comp_a' && r.outlet === 'second')[0];
2) if the route does not exist add it to the configuration.
if(!route){
this.router.config.unshift({path:'comp_a',outlet:'second',component:CompA})
}
we are using unshift method and not the push here because we don't want to add new route at the end. We always want to keep **
as the last route.
3) Then simply navigate to the route.
this.router.navigate([{outlets: {second: ['comp_a']}}]);
This solution can be helpful when the application is already loaded. But if you try to load a URL which has a path with a named outlet and if that route is not defined in the router configuration it will throw an error.
To overcome that situation you can listen to the NavigationStart event at the module level and there you can examine the URL and add routes accordingly. Though it is possible to do it does not feels clean to me. I hope this will help.
来源:https://stackoverflow.com/questions/55261876/using-the-angular-router-how-do-i-share-routes-across-multiple-named-outlets