I am trying to build a listing component in Angular2 that takes the items, the columns and the templates for the fields of the items from the user of the component. So I am trying to use ngTemplateOutlet
and ngOutletContext
(which I have read are experimental). But I cannot get it to work.
Here is a simplified component to demonstrate what I am trying to do:
<div *ngFor="let item of items> <span *ngFor="let column of columns> <template [ngOutletContext]="{ item: item }" [ngTemplateOutlet]="column.templateRef"></template> </span> </div>
Here is the usage of the component:
<my-component [items]="cars" [columns]="carColumns"> <template #model>{{item.model}}</template> <template #color>{{item.color}}</template> <template #gearbox>{{item.gearbox}}</template> </my-component>
And here is example data:
cars = [ { model: "volvo", color: "blue", gearbox: "manual" }, { model: "volvo", color: "yellow", gearbox: "manual" }, { model: "ford", color: "blue", gearbox: "automatic" }, { model: "mercedes", color: "silver", gearbox: "automatic" } ]; carColumns = [ { templateRef: "model" }, { templateRef: "color" }, { templateRef: "gearbox" } ];
Here is a plunker reproducing the issue after adapting the code according to Günters comment: https://plnkr.co/edit/jB6ueHyEKOjpFZjxpWEv?p=preview
ngTemplateOutlet is a directive. It instantiates a template dynamically using a template reference and context object as parameters. In this guide, we will learn how to use it in Angular. We will show you several ngTemplateOutlet examples to learn from.
ngTemplateOutlet is a powerful tool for creating customisable components. It is used by many Angular libraries to enable users to provide custom templates.
TemplateReflink Represents an embedded template that can be used to instantiate embedded views. To instantiate embedded views based on a template, use the ViewContainerRef method createEmbeddedView() .
You can define local variables on ng-template through let-name. When angular creates a template by calling createEmbeddedView it can also pass context that will be used inside ng-template. Using the key $implicit in the context object will set its value as default.
This is how you need to do this:
@Component({ selector: 'my-component', template: ` <div *ngFor="let item of items"> <span *ngFor="let column of columns"> <template [ngTemplateOutlet]="column.ref" [ngOutletContext]="{ item: item }"></template> </span> </div>` }) export class MyComponent { @Input() items: any[]; @Input() columns: any[]; } @Component({ selector: 'my-app', template: ` <div> <my-component [items]="cars" [columns]="columns"> <template #model let-item="item">{{item?.model}}</template> <template #color let-item="item">{{item?.color}}</template> </my-component> </div>` }) export class App { @ViewChild('model') model; @ViewChild('color') color; cars = [ { model: "volvo", color: "blue" }, { model: "saab", color: "yellow" }, { model: "ford", color: "green" }, { model: "vw", color: "orange" } ]; ngAfterContentInit() { this.columns = [ { ref: this.model }, { ref: this.color ] ]; } }
Plunker
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With