invoke pipe during run time using pipe name /metadata

后端 未结 2 1549
花落未央
花落未央 2020-12-09 22:33

I\'m trying to build a dynamic table where i wand to decide in run time which pipe to use (If Any).

I\'m trying to achieve something similar to (Sim

相关标签:
2条回答
  • 2020-12-09 23:04

    For runtime compile only you can create a directive which will compile template dynamically.

    UPDATE:

    Using compileModuleAndAllComponentsAsync for RC.6^

    dynamic-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^


    OBSOLETE SOLUTION

    In RC.5 you can use Compiler.compileComponentSync/Async to do that:

    dynamic-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, []);
          });
      }
    }
    

    And use it this way:

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

    See also the plunker sample RC.5 that demonstrates this feature.

    Anyway i think Günter's solution is preferable

    0 讨论(0)
  • 2020-12-09 23:22

    You can't apply pipes dynamically. What you can do is to build a "meta" pipe that decides what transformation(s) to do.

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

    and then use it like

    <td *ngIf="cell.pipe">{{cell.content | meta:[cell.pipe]}}</td>
    
    0 讨论(0)
自定义标题
段落格式
字体
字号
代码语言
提交回复
热议问题