Angular2在路由器插座外部获取路由器参数

问题描述 投票:9回答:5

我有一个仪表板应用程序,它包含一个树视图组件(列出各种内容节点)和一个仪表板编辑组件,它根据树的哪个分支选择呈现一些可编辑的内容。

例如树是这样的:

- Football
- - Premier League
- - - Arsenal
- - - Chelsea
- - - ...etc
- - Championship
- - - Derby
- - - ...etc

单击树中的“Arsenal”,它会在页面上的可编辑面板中为该团队呈现一些内容。

呈现子组件的组件如下所示:

@Component({
    selector: 'my-dashboard',
    template: `
        <div class="tree-panel-container">
            <div class="tree-panel-content">
                <content-tree [startNodeId]="startNodeIdContent"></content-tree>
            </div>
        </div>
        <router-outlet></router-outlet>
    `,
    directives: [
        ContentTreeComponent, 
        ContentDashboardComponent, 
        RouterOutlet
    ],
    providers: [
        HTTP_PROVIDERS
    ]
})

可编辑内容以router-outlet呈现,以便每个可编辑的内容具有其自己的不同URL,例如例如,example.com/content/edit/123,其中123是阿森纳内容的id。

一切正常。

但是,我想要做的是能够访问id组件中的content-tree路由参数。目前,我很确定我在该组件中的代码应该有效:

import {Component, Input, OnInit}   from '@angular/core';
import {Router, RouteParams}        from '@angular/router-deprecated';

import {ContentNode}                from './content-node';
import {ContentService}             from '../services/content.service';


@Component({
    selector: 'content-tree',
    directives: [ContentTreeComponent],
    template: `
        <ol class="tree">
            <li *ngFor="let contentNode of contentNodes" class="tree__branch" [ngClass]="{'tree__branch--has-children': contentNode.HasChildren}">
                <a *ngIf="contentNode.HasChildren" (click)="contentNode.toggle=!contentNode.toggle" class="tree__branch__toggle">
                    {{ !!contentNode.toggle ? '-' : '+' }}
                </a> 
                <a class="tree__branch__link" (click)="onSelect(contentNode)">{{ contentNode.Name }}</a>
                <content-tree *ngIf="contentNode.toggle" [startNodeId]="contentNode.Id"></content-tree>
            </li>
        </ol>
        <div class="error" *ngIf="errorMessage">{{errorMessage}}</div>
    `
})
export class ContentTreeComponent implements OnInit {

    constructor(
        private _contentService: ContentService,
        private _router: Router,
        private _routeParams: RouteParams
    ) { }

    errorMessage: string;

    @Input('startNodeId')
    private _startNodeId: number;

    contentNodes: ContentNode[];

    ngOnInit() { 
        let nodeId = +this._routeParams.get('id');
        console.log('nodeId = ' + nodeId);
        this.getContentNodes();
    }

    onSelect(contentNode: ContentNode) {
        this._router.navigate( ['ContentEdit', { id: contentNode.Id }]  );
    }

    getContentNodes() {
        this._contentService.getContentNodes(this._startNodeId)
            .subscribe(
                contentNodes => this.contentNodes = contentNodes,
                error =>  this.errorMessage = <any>error
            );
    }
}

但是nodeId方法中的ngOnInit变量总是以0的形式返回。

问题:是否只能访问由路由器出口提供的组件中的路由参数?如果是这样,那么处理这个的最好方法是创建第二个(命名,因为现在会有2个)路由器插座?如果没有,那么我做错了什么?

非常感谢。

编辑:

现在已经生成了一个工作(并且非常丑陋;))Plnkr来展示应用程序的基础知识:http://plnkr.co/edit/W3PVk3Ss5Wq59IbnLjaK?p=preview。看看应该发生什么的评论......

typescript angular angular2-routing
5个回答
3
投票

在新的路由器(> = RC.0 <= RC.2)中,这将是

  import 'rxjs/add/operator/first';
  ...

  constructor(private router:Router, private routeSerializer:RouterUrlSerializer, private location:Location) {
    router.changes.first().subscribe(() => {

    let urlTree = this.routeSerializer.parse(location.path());
      console.log('id', urlTree.children(urlTree.children(urlTree.root)[0])[0].segment);
    });
  }

另见Angular 2 RC1: Get parameters from the initial URL used


13
投票

Get the active route from outside a component in angular 2.1.0 and Router 3.1.0

我找到了一个很好的方法从应用程序内的任何地方获取显示路径中的所有参数,queryParmas,段和片段。只需将此代码添加到您需要的任何组件,或创建可在整个应用程序中注入的服务。

import { Router, NavigationEnd } from "@angular/router";
import { Component, OnInit } from '@angular/core';

...

export class MyComponentOrService implements OnInit {

constructor(private router: Router) {}

ngOnInit() {

  /* this subscription will fire always when the url changes */
  this.router.events.subscribe(val=> {

    /* the router will fire multiple events */
    /* we only want to react if it's the final active route */
    if (val instanceof NavigationEnd) {

     /* the variable curUrlTree holds all params, queryParams, segments and fragments from the current (active) route */
     let curUrlTree = this.router.parseUrl(this.router.url);
     console.info(curUrlTree);
    }
  });
}
...

4
投票

是否只能访问由路由器出口提供的组件中的路由参数?

是的,<router-outlet></router-outlet>告诉Angular2将包含组件视为“路由”组件。因此,您无法将一个RouteParams实例注入到类中,因为它没有通过路由指令实例化。

如果没有,那么我做错了什么?

我不会说你做错了什么,你只是对它的设计有误解。我也有这种最初的误解。我发现this Angular2文章是理解如何传递数据以及如何在父组件和子组件之间进行通信的重要来源。


In your specific case I'd suggest removing the RouteParams from the constructor of the ContentTreeComponent as it will only be available if rendered from a "routing" component.
export class ContentTreeComponent implements OnInit {

    constructor(
        private _contentService: ContentService,
        private _router: Router
    ) { }

    // Omitted for brevity...
}

然后,为了获得id,您可能需要分享更多的顶级代码,以便我可以看到它来自哪里......


1
投票

这个解决方案对我有用:complete example

constructor(
  private readonly router: Router,
  private readonly rootRoute: ActivatedRoute,
){
  router.events.pipe(
    filter(e => e instanceof NavigationEnd),
    map(e => this.getParams(this.rootRoute))
  ).subscribe(params => {
   //
  });
}

private getParams(route: ActivatedRoute): Params {
  // route param names (eg /a/:personId) must be ditinct within
  // a route otherwise they'll be overwritten
  let params = route.snapshot.params
  params = { ...route.snapshot.queryParams, ...params}
  if(route.children){
    for(let r of route.children){
      params = {...this.getParams(r), ...params};        
    }
  }
  return params;
}

积分兑换Toxicable


0
投票

由于这篇文章中找到的解决方案无法解决我的问题,我刚刚添加了一个其他解决方案,目前可以修复或帮助您在另一篇文章中处理类似问题:Angular 2: How do I get params of a route from outside of a router-outlet

© www.soinside.com 2019 - 2024. All rights reserved.