在 运行 时间内使用管道名称/元数据调用管道

invoke pipe during run time using pipe name /metadata

我正在尝试构建一个动态 table,我想在 运行 时间 中决定使用哪个管道(如果有的话)。

我正在尝试实现类似于(简体)的东西:

export class CellModel {
     public content: any;
     public pipe: string
}

Table

<tbody>
     <tr *ngFor="let row of data">
         <template ngFor let-cell [ngForOf]=row>
           <td *ngIf="cell.pipe">{{cell.content | cell.pipe}}</td>
           <td *ngIf="!cell.pipe">{{cell.content}}</td>
     </tr>
</tbody>

我知道这个例子出错了。我可以使用 Reflect 是某种方式还是其他解决方案?

您不能动态应用管道。您可以做的是构建一个 "meta" 管道来决定要执行的转换。

@Pipe({
  name: 'meta'
})
class MetaPipe implements PipeTransform {
  transform(val, pipes:any[]) {
    var result = val;
    for(var pipe of pipes) {
      result = pipe.transform(result);
    }
    return result;
  }
}

然后像

一样使用它
<td *ngIf="cell.pipe">{{cell.content | meta:[cell.pipe]}}</td>

对于仅运行时编译,您可以创建一个动态编译模板的指令。

更新:

compileModuleAndAllComponentsAsync用于RC.6^

动态-pipe.ts

  ngAfterViewInit() {
    const data = this.data.content;
    const pipe = this.data.pipe;

    @Component({
      selector: 'dynamic-comp',
      template: '{{ data | ' + pipe  + '}}'
    })
    class DynamicComponent  {
        @Input() public data: any;
    };

    @NgModule({
      imports: [BrowserModule],
      declarations: [DynamicComponent]
    })
    class DynamicModule {}

    this.compiler.compileModuleAndAllComponentsAsync(DynamicModule)
      .then(({moduleFactory, componentFactories}) => {
        const compFactory = componentFactories.find(x => x.componentType === DynamicComponent);
        const injector = ReflectiveInjector.fromResolvedProviders([], this.vcRef.parentInjector);
        const cmpRef = this.vcRef.createComponent(compFactory, 0, injector, []);
        cmpRef.instance.data = data;
      });
  }

Plunker sample RC.6^


过时的解决方案

RC.5 中,您可以使用 Compiler.compileComponentSync/Async 来做到这一点:

动态-pipe.ts

@Directive({
  selector: 'dynamic-pipe' 
})
export class DynamicPipe {
  @Input() data: CellModel;

  constructor(private vcRef: ViewContainerRef, private compiler: Compiler) {}

  ngAfterViewInit() {
    const metadata = new ComponentMetadata({
      template: '{{ data | ' + this.data.pipe  + '}}'
    });

    const data = this.data.content;
    const decoratedCmp = Component(metadata)(class DynamicComponent {  data = data; });

    this.compiler.compileComponentAsync(decoratedCmp)
      .then(factory => {
        const injector = ReflectiveInjector.fromResolvedProviders([], 
           this.vcRef.parentInjector);
        this.vcRef.createComponent(factory, 0, injector, []);
      });
  }
}

并这样使用:

<template ngFor let-cell [ngForOf]="row">
   <td><dynamic-pipe [data]="cell"></dynamic-pipe></td>
</template>

另请参阅演示此功能的 plunker sample RC.5

无论如何我认为 Günter 的解决方案更可取