Call a pipe at runtime using name / metadata

I am trying to create a dynamic table in which I wand will decide at runtime which channel to use (If Any).

I am trying to achieve something similar (simplified):

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> 

I understand that this example gives an error. Can I use Reflect in some way or some other solution?

+6
angular angular2-pipe
source share
2 answers

Dynamic dynamic applications cannot be used. What you can do is build a “meta” that decides which conversions (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> 
+5
source share

To compile at run time, you can create a directive that will dynamically compile the template.

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

RC.6 plunger example ^


OBSOLETE SOLUTION

In RC.5, you can use Compiler.compileComponentSync/Async for this:

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 like this:

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

See also the plunker RC.5 sample , which demonstrates this feature.

In any case, I think the Günter solution is preferable

+4
source share

All Articles