programing

각도 2: 상위 구성 요소에서 RouteParams 가져오기

abcjava 2023. 9. 3. 12:07
반응형

각도 2: 상위 구성 요소에서 RouteParams 가져오기

상위 구성 요소에서 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');
  }

  ...
}

그러나 하위 구성 요소에서 동일한 '사용자 이름' 매개 변수를 얻으려면 어떻게 해야 합니까?위와 같은 속임수를 쓰는 것은, 그것을 하지 않습니다.이러한 매개변수가 프로파일 구성요소에 정의되어 있기 때문입니까?

@Component({
  ...
})

export class ChildOneComponent {

  public username: string;

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

  ...
}

업데이트:

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

사용하려고 하면 안 됩니다.RouteParams의 신의에ChildOneComponent.

대신 사용하십시오!

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


  ...
}

업데이트: 이 풀 요청(각형 베타)부터입니다.: https://github.com/angular/angular/pull/7163

이제 다음 명령을 사용하지 않고 현재 지침에 액세스할 수 있습니다.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: 각도 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'];
  }

  ...
}

귄터 조흐바우어가 언급했듯이, 저는 제 문제를 해결하기 위해 https://github.com/angular/angular/issues/6204#issuecomment-173273143 의 코멘트를 사용했습니다.사용했습니다.Injectorangular2/core부모의 경로 매개 변수를 가져옵니다.각 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);
}

저는 부모(정확히는 2번째 조상) 인젝터를 요청하고 다음을 얻음으로써 못생겼지만 작동하는 솔루션을 찾았습니다.RouteParams여기서부터

비슷한 것

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

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

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

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);
  });

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

@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');
  }

  ...
}

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

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

@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

RC6의 라우터 3.0.0-rc.2(RC5에서도 작동할 수 있음)에서는 다음 라이너를 사용하여 관찰할 수 없는 경우에 대비하여 URL에서 경로 매개변수를 스냅샷으로 가져올 수 있습니다.

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

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

constructor(private route: ActivatedRoute) {};

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

저는 결국 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];
  }

  ...
}  

FINAL에서는 RXJS의 도움을 거의 받지 않고 (자녀와 부모로부터) 두 지도를 결합할 수 있습니다.

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

다음과 같은 질문이 있을 수 있습니다.

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

다음을 사용하여 스냅샷에서 이 작업을 수행할 수 있지만 변경되면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();
  }
}

Angular 8의 상위 구성 요소에서 RouteParams 가져오기 -

http://localhost:4200/partner/student-profile/1234/info 경로가 있습니다.

상위 경로 - 학생 프로필

매개 변수 - 1234(student_id)

하위 경로 - 정보


하위 경로의 매개 변수 액세스(info) -

수입품

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에 매개 변수 값이 있습니다.

언급URL : https://stackoverflow.com/questions/34500147/angular-2-getting-routeparams-from-parent-component

반응형