有没有更好的方法来获得Angular2中的祖先路线参数?

时间:2017-03-08 15:01:22

标签: angular typescript angular2-routing

我需要从不是父母而不是祖母的路线获得参数,它只是在上面的某个地方,沿着通向根的路径。我知道Angular 2: getting RouteParams from parent component或通过共享服务所显示的方法,但我把自己置于(至少我认为如此)的情况使得那些不适合它的方法。所以这就是我得到的:

我从父上下文中懒惰地加载了需要MediaSource的子模块。情况或多或少看起来像这样的路由配置:

MediaSource[] allSources = // ...
ConcatenatingMediaSource source = new ConcatenatingMediaSource(allSources);

ExoPlayer player = // ..
player.prepare(source);

// ...

@Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
    // Can I retrieve the index of the MediaSource currently being played here?
    // If not, where!?
}

id需要加载属于给定// Parent/outer module routing const outerRoutes: Routes = [ { path: 'container/:containerId', component: ContainerComponent, children: [ { path: 'model', loadChildren: 'app/container/model/model.module#ModelModule' }, { path: '', component: ContainerDetailsComponent } ] } ]; // Child/inner module routing const innerRoutes: Routes = [ { path: '', component: ModelComponent, children: [ { path: ':id', component: ModelDetailsComponent }, { path: '', component: ModelsComponent } ] } ]; 的所有ModelsComponent个实例。所以我决定通过Model方法但是在写完第二Container之后我的牙齿开始受伤了,还有第三个来了:

.parent

共享服务在某种程度上是一种选择,但是由于子模块被延迟加载,我必须把它放在核心模块中,使它非常全局(我不喜欢)。

经过一段时间的努力之后,我来到了一段代码,它只需要将所有.parent带到根目录,将它们组合起来,查找param并使用它。我不喜欢它,因为在我看来它太复杂,不可读并且从一英里发臭(或者换句话说就像血腥一样),但是有效并且我不必关心嵌套是否变化。我只需要确保this.route.parent.parent.parent.params .switchMap((params: Params) => this.modelService.getAllBelongingTo(params['containerId'])) .subscribe( (models: Model[]) => this.models = models, error => this.raceEvent = null ); 在通往root的路径上的某个地方。

ActivatedRoute

有没有更好的方法来处理所描述的情况?

2 个答案:

答案 0 :(得分:7)

一般来说,我认为您的方法确实有意义。

我不知道代码的确切背景,但它确实感觉像是一个想要了解有关父实例数据的子组件,我同意@ Aravind的评论,这可能是最好的处理在全球状态管理解决方案中,例如redux或ngrx。话虽这么说,如果这就是你需要的全部,我理解你不会想要引入那种复杂程度。

我只会对您的rxchain进行微调,以便更具可读性。

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

import { Model } from './model';
import { ModelService } from './model.service';

@Component({
    ...
})
export class ModelsComponent implements OnInit {
    models: Model[];

    constructor(
        private route: ActivatedRoute,
        private modelService: ModelService) { }

    ngOnInit() {
        const paramsArr = this.route.pathFromRoot;

        Observable.from(paramsArr)
            .map(route => route.params)
            .filter(params => params.containerId)
            .switchMap(containerId => this.modelService.getAllBelongingTo(containerId))
            .subscribe(
                (models: Model[]) => {
                    // yay! we got sth
                    this.models = models;
                },
                error => {
                    // handle big nono
                }
            );
    }
}

但是请注意,当有一个containerId作为父级的参数时,此实现只会设置this.models

编辑1:修正错别字

答案 1 :(得分:0)

我遇到了同样的问题,在找到这个答案后,我创建了一个名为getParams()的函数,它获取了父项和当前根的所有参数。

它将所有参数组合在一起并缩小为单个地图。

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { ServicosService } from '@service/core/servicos.service';
import { ActivatedRoute } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { map, combineAll } from 'rxjs/operators';

@Injectable()
export abstract class HttpServiceRouted {
  constructor(
    protected http: HttpClient,
    protected servicos: ServicosService,
    protected route: ActivatedRoute
  ) {}

  getParams() {
    return Observable.from(this.route.pathFromRoot.concat(this.route)).pipe(
      map(route => route.params),
      combineAll(),
      map((params: any[]) =>
        params.reduce(
          // tslint:disable-next-line:no-shadowed-variable
          (map: Map<string, string>, obj) => {
            Object.keys(obj).forEach(key => {
              map.set(key, obj[key]);
            });
            return map;
          },
          new Map<string, string>()
        )
      )
    );
  }
}

用法:

this.getParams().subscribe((params: ParamMap) => {
  const id = params.get('id');
});