Angular 2 : 부모 구성 요소에서 RouteParams 가져 오기


79

상위 구성 요소에서 RouteParams를 가져 오려면 어떻게해야합니까?

App.ts:

@Component({
  ...
})

@RouteConfig([
  {path: '/', component: HomeComponent, as: 'Home'},
  {path: '/:username/...', component: ParentComponent, as: 'Parent'}
])

export class HomeComponent {
  ...
}

그런 다음에서 ParentComponent사용자 이름 매개 변수를 쉽게 얻고 자식 경로를 설정할 수 있습니다.

Parent.ts:

@Component({
  ...
})

@RouteConfig([
  { path: '/child-1', component: ChildOneComponent, as: 'ChildOne' },
  { path: '/child-2', component: ChildTwoComponent, as: 'ChildTwo' }
])

export class ParentComponent {

  public username: string;

  constructor(
    public params: RouteParams
  ) {
    this.username = params.get('username');
  }

  ...
}

그렇다면 해당 하위 구성 요소에서 동일한 '사용자 이름'매개 변수를 어떻게 얻을 수 있습니까? 위와 같은 트릭을 수행하면 안됩니다. 그 매개 변수는 ProfileComponent 또는 무언가에 정의되기 때문에 ??

@Component({
  ...
})

export class ChildOneComponent {

  public username: string;

  constructor(
    public params: RouteParams
  ) {
    this.username = params.get('username');
    // returns null
  }

  ...
}

아이들의 입력 속성은 어떻습니까? 예 : 상위 템플릿에서 :<child-one-component [username]="username"> ...
Mark Rajcok

그것도 작동 <routerlink [username]="username">...합니까? 그리고 그게 @MarkRajcok으로가는 길인가요?
Aico Klein Ovink 2015

같은 <a [router-link]="[ './....', {username: username} ]것이 효과가 있는지 묻는 것 같습니다 . 죄송합니다. 그게 효과가 있을지 모르겠습니다. (나는 아직 많은 라우팅 연주하지 않았습니다.)
마크 Rajcok

죄송합니다 @MarkRajcok, 내가 잘못 입력했습니다 .. 그게 <router-outlet></router-outlet>입력해야 한다는 뜻 입니다. 자식 노선 ..이 렌더링 줘야하기 때문에
AICO 클라인 Ovink에게

답변:


72

최신 정보:

Angular2 final이 공식적으로 출시되었으므로 올바른 방법은 다음과 같습니다.

export class ChildComponent {

    private sub: any;

    private parentRouteId: number;

    constructor(private route: ActivatedRoute) { }

    ngOnInit() {
        this.sub = this.route.parent.params.subscribe(params => {
            this.parentRouteId = +params["id"];
        });
    }

    ngOnDestroy() {
        this.sub.unsubscribe();
    }
}

실물:

다음은 "@ angular / router": "3.0.0-alpha.6"패키지를 사용하여 수행 한 방법입니다.

export class ChildComponent {

    private sub: any;

    private parentRouteId: number;

    constructor(
        private router: Router,
        private route: ActivatedRoute) {
    }

    ngOnInit() {
        this.sub = this.router.routerState.parent(this.route).params.subscribe(params => {
            this.parentRouteId = +params["id"];
        });
    }

    ngOnDestroy() {
        this.sub.unsubscribe();
    }
}

이 예에서 경로의 형식은 다음과 같습니다. / parent / : id / child / : childid

export const routes: RouterConfig = [
    {
        path: '/parent/:id',
        component: ParentComponent,
        children: [
            { path: '/child/:childid', component: ChildComponent }]
    }
];

2
내가 처음에 어리석게 시도한 것처럼 생성자가 아닌 ngOnInit 에서 이것을 호출해야합니다 .
카메론

2
Angular 5.2 이후에는 parent1 회 이상 횡단 할 필요가없는 다른 방법이 있습니다 . stackoverflow.com/a/48511516/4185989를 참조하십시오 .이 답변 의 subscribe/ unsubscribe패턴을 고려할 가치가 있습니다.
jmq

Angular 6에서this.activatedRoute.parent.snapshot.params.someParam
Tasnim Reza

@jmq가 가리키는 솔루션은 angular 6에도 가장 적합하며 부모 ID에 대해 별도로 구독 할 필요가 없습니다.
학습 중 ...

완벽한 솔루션! 부모 매개 변수를 얻기 위해 구독해야하는 이유를 구입합니까? 매개 변수가 이미 있습니다! :: 생각 ::
moreirapontocom

10

당신은 RouteParams당신의 ChildOneComponent.

RouteRegistry대신을 사용하십시오 !

@Component({
  ...
})

export class ChildOneComponent {

  public username: string;

  constructor(registry: RouteRegistry, location: Location) {
    route_registry.recognize(location.path(), []).then((instruction) => {
      console.log(instruction.component.params['username']);
    })
  }


  ...
}

업데이트 : 이 풀 리퀘스트 (angular beta.9) : https://github.com/angular/angular/pull/7163

이제 .NET없이 현재 명령어에 액세스 할 수 있습니다 recognize(location.path(), []).

예:

@Component({
  ...
})

export class ChildOneComponent {

  public username: string;

  constructor(_router: Router) {
    let instruction = _router.currentInstruction();
    this.username = instruction.component.params['username'];
  }

  ...
}

아직 해보지 않았지만

자세한 내용은 다음을 참조하세요.

https://github.com/angular/angular/blob/master/CHANGELOG.md#200-beta9-2016-03-09 https://angular.io/docs/ts/latest/api/router/Router-class .html

업데이트 2 : angular 2.0.0.beta15에서와 같은 작은 변경 :

이제는 currentInstruction더 이상 함수가 아닙니다. 또한 root라우터 를로드해야 합니다. (보고를 위해 @ Lxrd-AJ에게 감사드립니다)

@Component({
  ...
})

export class ChildOneComponent {

  public username: string;

  constructor(_router: Router) {
    let instruction = _router.root.currentInstruction;
    this.username = instruction.component.params['username'];
  }

  ...
}

이것이 자식 루트에 대해 수행되어야하는 방식입니까? 또한 하위 경로가 상위 구성 요소의 경로 매개 변수를 볼 수없는이 문제에 직면하고 있습니다. 예를 들어 경로 / users / : user_id / posts / : post_id, 게시물 구성 요소에서 user_id를 가져올 수 없습니다 .... RouteRegistry를 사용해야하는 것이 나에게 해키 한 것 같습니다.
mharris7190

@ mharris7190 내 대답을 업데이트했습니다. angular beta.9부터 라우터 구성 요소에서 직접 현재 지침을 얻을 수 있습니다.
ProGM 2016

업데이트 해주셔서 감사합니다. beta.6에서 beta.13으로 업그레이드하려고하므로 업그레이드 한 후에 사용해 보겠습니다.
mharris7190 2016

3
이 답변에 대한 약간의 편집, 사용 _router.root.currentInstruction.component.params['id']. 이제 루트 라우터가 아닌 루트 라우터에서 currentInstruction을 얻으므로 루트에 중점을 둡니다 _router. 추신 : 나는 사용하고 있습니다angular2.0.0-beta.15
Lxrd-AJ

_router.root가 더 이상 존재하지 않습니다. (나는 Angular 2.4.7을 사용합니다)
Eivind Gussiås Løkseth

7

Günter Zöchbauer가 언급했듯이 https://github.com/angular/angular/issues/6204#issuecomment-173273143 의 주석을 사용하여 문제를 해결했습니다. Injector클래스를 사용하여 angular2/core부모의 routeparams를 가져 왔습니다. 각도 2는 깊게 내포 된 루트를 처리하지 않는 것으로 나타났습니다. 아마도 그들은 미래에 그것을 추가 할 것입니다.

constructor(private _issueService: IssueService,
            private _injector: Injector) {}

getIssues() {
    let id = this._injector.parent.parent.get(RouteParams).get('id');
    this._issueService.getIssues(id).then(issues => this.issues = issues);
}

8
이것은 angular2 RC 라우터에서 더 이상 작동하지 않습니다.
Inn0vative1

6

나는 부모 (정확히 두 번째 조상) 인젝터를 요청하고 여기에서 가져옴으로써 추악하지만 작동하는 해결책을 찾았 RouteParams습니다.

같은 것

@Component({
  ...
})
export class ChildOneComponent {
  public username: string;

  constructor(injector: Injector) {
    let params = injector.parent.parent.get(RouteParams);

    this.username = params.get('username');
  }
}

공유해 주셔서 감사합니다. 앞으로이 문제를 어떻게 처리할지에 대한 앵귤러 팀의 버그 추적기 항목이나 진술이 있습니까?
Marcus Riemer

그 .parent는 RC3에 제거 된 것 같은데
theFreedomBanana

4

RC5 + @ angular / router ":"3.0.0-rc.1 해결책 :this.router.routerState.queryParams 더 이상 사용되지 않는 것 같습니다 . 다음과 같이 상위 경로 매개 변수를 가져올 수 있습니다.

constructor(private activatedRoute: ActivatedRoute) {
}    

this.activatedRoute.parent.params.subscribe(
  (param: any) => {
    let userId = param['userId'];
    console.log(userId);
  });

2

인젝터에서 자식 구성 요소 내부의 부모 경로 구성 요소를 가져온 다음 자식 구성 요소에서 가져올 수 있습니다. 이런 경우

@Component({
  ...
})

export class ChildOneComponent {

  public username: string;

  constructor(
    public params: RouteParams
    private _injector: Injector

  ) {
    var parentComponent = this._injector.get(ParentComponent)

    this.username = parentComponent.username;
    //or
    this.username = parentComponent.params.get('username');
  }

  ...
}

2

코드에 대한 단위 테스트를 작성하려는 경우 Injector 인스턴스를 자식 구성 요소의 생성자에 전달하는 것이 좋지 않을 수 있습니다.

이 문제를 해결하는 가장 쉬운 방법은 필요한 매개 변수를 저장하는 상위 컴포넌트에 서비스 클래스를 갖는 것입니다.

@Component({
    template: `<div><router-outlet></router-outlet></div>`,
    directives: [RouterOutlet],
    providers: [SomeServiceClass]
})
@RouteConfig([
    {path: "/", name: "IssueList", component: IssueListComponent, useAsDefault: true}
])
class IssueMountComponent {
    constructor(routeParams: RouteParams, someService: SomeServiceClass) {
        someService.id = routeParams.get('id');
    }
}

그런 다음 동일한 서비스를 하위 구성 요소에 삽입하고 매개 변수에 액세스합니다.

@Component({
    template: `some template here`
})
class IssueListComponent implements OnInit {
    issues: Issue[];
    constructor(private someService: SomeServiceClass) {}

    getIssues() {
        let id = this.someService.id;
        // do your magic here
    }

    ngOnInit() {
        this.getIssues();
    }
}

부모 구성 요소 데코레이터에서 "제공자"를 사용하여 이러한 서비스의 범위를 부모 구성 요소와 해당 자식 구성 요소로 지정해야합니다.

Angular 2의 DI 및 범위에 대한이 기사를 추천합니다. http://blog.thoughtram.io/angular/2015/08/20/host-and-visibility-in-angular-2-dependency-injection.html


2

RC6, 라우터 3.0.0-rc.2 (아마도 RC5에서도 작동 함)에서이 하나의 라이너로 관찰 할 수있는 매개 변수없이 매개 변수가 변경되지 않는 경우 URL에서 경로 매개 변수를 스냅 샷으로 가져올 수 있습니다.

this.route.snapshot.parent.params['username'];

다음과 같이 ActivatedRoute를 주입하는 것을 잊지 마십시오.

constructor(private route: ActivatedRoute) {};


2

RxJS Observable.combineLatest를 사용하면 관용적 매개 변수 처리에 가까운 것을 얻을 수 있습니다.

import 'rxjs/add/operator/combineLatest';

import {Component} from '@angular/core';
import {ActivatedRoute, Params} from '@angular/router';
import {Observable} from 'rxjs/Observable';

@Component({ /* ... */ })
export class SomeChildComponent {
  email: string;
  id: string;

  constructor(private route: ActivatedRoute) {}

  ngOnInit() {
    Observable.combineLatest(this.route.params, this.route.parent.params)
        .forEach((params: Params[]) => {
          this.id = params[0]['id'];
          this.email = params[1]['email'];
        });
  }
}

1

나는 Angular 2 rc.1에 대해 이런 종류의 해킹을 작성했습니다.

import { Router } from '@angular/router-deprecated';
import * as _ from 'lodash';

interface ParameterObject {
  [key: string]: any[];
};

/**
 * Traverse route.parent links until root router and check each level
 * currentInstruction and group parameters to single object.
 *
 * e.g.
 * {
 *   id: [314, 593],
 *   otherParam: [9]
 * }
 */
export default function mergeRouteParams(router: Router): ParameterObject {
  let mergedParameters: ParameterObject = {};
  while (router) {
    let currentInstruction = router.currentInstruction;
    if (currentInstruction) {
      let currentParams = currentInstruction.component.params;
      _.each(currentParams, (value, key) => {
        let valuesForKey = mergedParameters[key] || [];
        valuesForKey.unshift(value);
        mergedParameters[key] = valuesForKey;
      });
    }
    router = router.parent;
  }
  return mergedParameters;
}

이제보기에서 읽기 대신보기에서 매개 변수를 수집 RouteParams하여 라우터를 통해 가져옵니다.

@Component({
  ...
})

export class ChildishComponent {

  constructor(router: Router) {
    let allParams = mergeRouteParams(router);
    let parentRouteId = allParams['id'][0];
    let childRouteId = allParams['id'][1];
    let otherRandomParam = allParams.otherRandomParam[0];
  }

  ...
}  

잘 작동합니다! 결국 표준 클래스 MergedRouteParamsget메서드 를 구현 하는 클래스 내부에서이 메서드를 개인용으로 만들었습니다 RouteParams(두 번째 매개 변수는 index, 기본값은 0).
Jim Buck

0

RXJS의 도움이 거의없는 FINAL 에서는 두 맵을 결합 할 수 있습니다 (하위 및 상위에서) :

(route) => Observable
    .zip(route.params, route.parent.params)
    .map(data => Object.assign({}, data[0], data[1]))

다른 질문이있을 수 있습니다.

  • 위에서 사용하는 것이 정말 좋은 생각입니까?-커플 링 (부모의 매개 변수와 자식 구성 요소를 결합하기 때문에-API 수준이 아닌-숨겨진 커플 링),
  • RXJS 측면에서 적절한 접근 방식입니까 (하드 코어 RXJS 사용자 피드백이 필요합니다.)

0

다음과 같이 스냅 샷에서 수행 할 수 있지만 변경 될 경우 id속성이 업데이트되지 않습니다.

이 예제는 또한 모든 상위 매개 변수 변경 사항을 구독하고 모든 매개 변수 관찰 가능 항목을 병합하여 관심있는 항목을 찾는 방법을 보여줍니다. 그러나 매개 변수 키 / 이름이 동일한 여러 상위 항목이있을 수 있으므로이 방법에주의하십시오.

import { Component } from '@angular/core';
import { ActivatedRoute, Params, ActivatedRouteSnapshot } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { Subscription } from 'rxjs/Subscription';
import 'rxjs/add/observable/merge';

// This traverses the route, following ancestors, looking for the parameter.
function getParam(route: ActivatedRouteSnapshot, key: string): any {
  if (route != null) {
    let param = route.params[key];
    if (param === undefined) {
      return getParam(route.parent, key);
    } else {
      return param;
    }
  } else {
    return undefined;
  }
}

@Component({ /* ... */ })
export class SomeChildComponent {

  id: string;

  private _parameterSubscription: Subscription;

  constructor(private route: ActivatedRoute) {
  }

  ngOnInit() {
    // There is no need to do this if you subscribe to parameter changes like below.
    this.id = getParam(this.route.snapshot, 'id');

    let paramObservables: Observable<Params>[] =
      this.route.pathFromRoot.map(route => route.params);

    this._parametersSubscription =
      Observable.merge(...paramObservables).subscribe((params: Params) => {
        if ('id' in params) {
          // If there are ancestor routes that have used
          // the same parameter name, they will conflict!
          this.id = params['id'];
        }
      });
  }

  ngOnDestroy() {
    this._parameterSubscription.unsubscribe();
  }
}

0

Angular 8의 부모 구성 요소에서 RouteParams 가져 오기-

나는 경로가 // localhost를 : 4200 / 파트너 / 학생 프로필 / 1234 / 정보 HTTP를

학부모 경로 -학생 프로필

Param -1234 (student_id)

어린이 경로 -정보


하위 경로 (정보)에서 매개 변수에 액세스-

수입

import { ActivatedRoute, Router, ParamMap } from '@angular/router';

건설자

constructor(private activatedRoute: ActivatedRoute, private router: Router) { }

상위 경로 매개 변수에 액세스

this.activatedRoute.parent.paramMap.subscribe((params: ParamMap) => this.studentId = (params.get('student_id')));


이제 변수 studentId 에 매개 변수 값이 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.