使用Angular路由器如何在多个命名出口之间共享路由

时间:2019-03-20 13:28:58

标签: angular angular-router

我有一个应用程序,希望在该应用程序的多个位置显示相同的一组组件/路线。想想多个面板或侧栏之类的东西,用户可以根据自己的选择在多个位置显示相同的组件。

例如,用户可能希望“在侧面板中显示状态组件”或“在页面的右下方面板中显示状态组件”。

(在我的情况下,插座的数量是固定的,但是对于具有动态数量的卡的仪表板样式的UI可以使用相同的概念,每张卡都有要加载组件的路线)

我的想法是为此使用带有命名插座的角度路由器。这样一来,就可以轻松重用支持动态创建的组件,并将当前路由状态保留在URL中,以方便重新加载。

例如,URL可能类似于:

https://.../app(side:status_comp//popup:other_comp)

我已经命名了出口,但是我不知道该怎么做,是在多个命名出口之间重用路由,而无需在路由器配置中复制路由。

例如:

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' }
];

简化模板:

<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>

然后使用以下方法将组件路由到插座:

this.router.navigate([{outlets: {first: ['comp_a']}}]);

我想设置路由器到给定组件的一条单一路由,然后可以使用任何已定义的路由调用router.navigate,但告诉它将该路由加载到指定的插座中。

>

有没有办法做到这一点。

这是stackblitz上的一个示例,其中包含所有设置。 ng-router-reuse app

我要进行的更改显示在上方,并且在路由定义中也是如此。

有什么想法吗?

注意:我知道我可以使用Angular CDK中的Portal之类的东西并动态加载组件。不过,问题在于,用户看到的状态不会存储到URL中以由路由器进行管理,并且还阻止了路由器的延迟加载。

1 个答案:

答案 0 :(得分:0)

您似乎可以在导航时在运行时动态更新路由器配置。这是一个例子。 https://stackblitz.com/edit/ng-router-reuse-c7j96a

这是一个简短的解释。

1)在链接或按钮上,单击以在路由器配置中找到路由。

 let route = this.router.config.filter(r => r.path === 'comp_a' && r.outlet === 'second')[0];

2)如果路由不存在,请将其添加到配置中。

if(!route){
  this.router.config.unshift({path:'comp_a',outlet:'second',component:CompA})
}

我们使用的是unshift方法,而不是此处的推送,因为我们不想在末尾添加新路线。我们始终希望将**保留为最后一条路线。

3)然后只需导航至路线即可。

this.router.navigate([{outlets: {second: ['comp_a']}}]);

该解决方案在已加载应用程序时可能会有所帮助。但是,如果您尝试加载的URL的路径带有命名出口,并且该路由未在路由器配置中定义,则会抛出错误。

要克服这种情况,您可以在模块级别监听NavigationStart事件,然后可以在其中检查URL并相应地添加路由。虽然可以做到,但对我来说并不干净。我希望这会有所帮助。