提供的管道无权访问路由解析数据

Provided Pipe doesn't have access to route resolved data

我有一个管道需要访问路由数据才能很好地构建:

export class LevelPercentagePipe implements PipeTransform {

  levelDictionnary: LevelDictionnary;

  constructor(private route: ActivatedRoute) {
    this.levelDictionnary = new LevelDictionnary(this.route.snapshot.data['prerequisiteLists']);
  }
}

此数据在路由模块中解析:

{
  path: 'xxx',
  loadChildren: './xxx/xxx.module#XxxModule',
  resolve: {
    prerequisiteLists: PrerequisiteResolver
  }
}

如果在 html 模板中使用管道,它在我的应用程序的其他地方也有效。 但在这种特殊情况下,我需要在我的 component.ts 文件中使用这个管道。所以我在具体的功能模块中提供了它:

@NgModule({
  declarations: [...],
  imports: [...],
  providers: [LevelFilterPipe],
})

但现在当它被注入我的组件构造函数时,它似乎不知道 ActivatedRoute 中的数据。

constructor(
        private profileService: ProfileService,
        private nameFilterPipe: NameFilterPipe,
        private levelFilterPipe: LevelFilterPipe
      ) {}

这行不通。

所以我需要手动构建管道。

constructor(
    private profileService: ProfileService,
    private route: ActivatedRoute,
    private scorePipe: ScorePipe,
    private nameFilterPipe: NameFilterPipe
  ) {
    // We have to inject route data and scorePipe manually because it's not injected automatically.
    this.levelFilterPipe = new LevelFilterPipe(this.route, this.scorePipe);
  }

还有其他方法可以自动从 ActivatedRoute 注入数据吗?

管道不是供应商。将管道放在组件的提供者数组中不会有太大作用。

如果你想让它工作,你可以简单地在你的组件中创建你的管道实例并传递当前路由。

constructor(private route: ActivatedRoute) {
  const pipeInstance = new MyPipe(ths.route);
}

你也可以尝试在你的管道中注入,像这样:

constructor(@Inject(forwardRef(() => ActivatedRoute)) private route: ActivatedRoute) {}

但我不确定这是否可行。

由于 Pipe 只是另一个 TypeScript class,如果用 @Injectable() 装饰器装饰,它可以作为依赖项注入。

因此,如果您在管道上方添加 @Injectable(),那么您的第一种方法将会奏效。

像这样:

import { Pipe, PipeTransform, Injectable } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

@Injectable()
@Pipe({
  name: 'level-filter'
})
export class LevelFilterPipe implements PipeTransform {

  constructor(private activatedRoute: ActivatedRoute) {}

  transform(value: any, args?: any): any {
    ...
  }

}

Here's a Sample Working StackBlitz Example for your ref.

PS: 不太确定这是否是一件好事。

您需要将 pipe 添加到您组件的供应商列表中。现在,您的管道注入将使用更新后的 ActivatedRoute 数据创建管道的新实例。

@Component({
  selector: '...',
  template: `...`:
  providers: [ YourPipeName ]
})

这是您问题的有效 StackBlitz project 示例。查看文件 hello.component.ts,此组件使用您提到的参数进行路由,删除此组件中提供的管道以重现您的问题。