如何从Angular2中的父组件获取子路由的:id参数

Posted

技术标签:

【中文标题】如何从Angular2中的父组件获取子路由的:id参数【英文标题】:How to get :id param of child route from parent component in Angular2 【发布时间】:2017-05-24 00:35:41 【问题描述】:

我正在尝试获取在

中定义的 :id 参数
RouterModule.forRoot([
  
    path: 'orders',
    component: ListComponent,
    children: [
      
        path: 'view/:id',
        component: ViewComponent
      ,
    ]
  
])

来自ListComponent

我已经试过了:

route: ActivatedRoute

route.params.subscribe(params => 
  let id = +params['id'];
)

来自ListComponent,但是params数组是空的,我想这是因为:id参数属于ViewComponent而不是ListComponent

如何在ListComponent 中获取id 参数?

【问题讨论】:

【参考方案1】:

另一种方法是在父组件中添加以下内容:

<ng-container *ngIf="routerOutlet.isActivated && routerOutlet.activatedRoute?.paramMap | async as paramMap">
child id is: paramMap.get('id')!
</ng-container>

<router-outlet #routerOutlet="outlet"></router-outlet>

当然,在子节点上使用解析器而不是参数会更好

<ng-container *ngIf="routerOutlet.activatedRouteData['child'] as child">
child id is : child.id
</ng-container>

<router-outlet #routerOutlet="outlet"></router-outlet>

假设子路由有类似的东西:

// ...
resolve: 
 child: 'childResolver',
,

子解析器可以在某个模块中:

// ...
providers: [
    provide: 'childResolver',
    useValue: (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => (
      id: route.paramMap.get('id')
    )
  ],

【讨论】:

【参考方案2】:

递归查找子参数不会总能得到您正在寻找的参数。特别是在移动路线时。

相反,可以使用 RxJS ReplaySubject 发布当前子 ID。

创建一个新服务:

@Injectable()
export class ChildIdService  
  current$ = new ReplaySubject<number>();

在子组件上导入并订阅重播主题:

export class ChildComponent implements OnInit 
  constructor(private ar: ActivatedRoute, public ci: ChildIdService)

  ngOnInit()
    this.ar.params.map(params => +params.id).subscribe(this.ci.current$);
  

在父组件上导入服务,使用异步管道订阅子值:

<span>Mother component child ID: ci.current$ | async</span>

这是一个有效的 sn-p:https://stackblitz.com/edit/angular-b8xome(将 /child/42 添加到浏览器应用预览以查看它是否有效)


或者将组件定义为同级并将父级添加为无组件路由,例如:https://vsavkin.com/the-powerful-url-matching-engine-of-angular-router-775dad593b03 在“使用相同数据的同级组件”下

【讨论】:

使用 ReplaySubject 而不是其他类型的主题有什么特别的原因吗?我仍在尝试掌握它们的用例,因此在这个示例中理解它会有所帮助。 ReplaySubject 将记住之前的结果,使 observable 对任何未来的订阅都是热的。如果您在多个地方订阅了这个 observable,并且想要访问之前推送的结果,这将很有帮助。【参考方案3】:

为了在父组件中获取子组件的参数,我使用了 ActivatedRoute 的 firstChild 属性,因为我只有子路由

route: ActivatedRoute

route.firstChild.params.subscribe(params => 
  let id = +params['id'];
);

【讨论】:

唯一正确的答案,因为在 Angular 中事情永远不会同步发生,而且这个答案也涵盖了订阅(异步)部分。【参考方案4】:

您可以使用firstChild 属性或ActivatedRoute 来获取子路由:

route.firstChild.snapshot.params['id']

【讨论】:

看起来属性 routerState 在 ActivatedRoute 上不存在,我也想在父组件而不是子组件中获取 id,所以我使用了 route.firstChild.params 我有点误读了这个问题,并假设@runyard 回答了你真正想要的。我更新了我的答案。 我使用了 route.snapshot.firstChild,而不是 route.firstChild.snapshot 还要检查 firstChild 是先定义的 在子加载之前不会有子参数。例如,您可以将 ActivatedRoute 注入子组件,并使子组件将参数传递给共享服务。 它正在工作,但我在控制台中遇到错误,类似“错误错误:ExpressionChangedAfterItHasBeenCheckedError:表达式在检查后已更改。以前的值:'true'。当前值:'false'”【参考方案5】:

如果只有一个子路由,您可以继续挖掘route.firstChild.params['id'],或者使用route.children[0].children[1].params['id'] 之类的东西使用括号表示法来挖掘多个级别以访问同级路由。在找到正确的水平时,它有点反复试验。

【讨论】:

以上是关于如何从Angular2中的父组件获取子路由的:id参数的主要内容,如果未能解决你的问题,请参考以下文章

Angular 2 @Input - 如何从父组件绑定子组件的 ID 属性?

从 Angular2 路由中的子组件调用 router.parent.navigate 方法时未触发组件构造函数和路由器生命周期挂钩

如何从 TypeScript 文件中的父级获取子组件变量和函数

如何将数据注入从路由器创建的 Angular2 组件中?

Angular 2 的异步加载路由数据和构建路由指令

如何在 Angular 中显示具有自己路由的父组件内的特定子组件?