invoke pipe during run time using pipe name /metadata

后端 未结 2 1554
花落未央
花落未央 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:

    
    

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

    Anyway i think Günter's solution is preferable

提交回复
热议问题