What I\'m trying to achieve is a generic component that is bound to an array of arbitrary objects that allows adding and removing rows dynamically when the view of each row
You could use ngTemplateOutlet to achieve it.
Following are the steps in implementing dynamic repeater:
First step is to provide a TemplateRef as a child element of the RepeaterComponent:
<repeater [repeaterArray]="repeaterObj">
<ng-template>
...
</ng-template>
</repeater>
Second step is to query this template within RepeaterComponent via @ContentChild:
export class RepeaterComponent {
@ContentChild(TemplateRef) itemTemplate: TemplateRef<any>;
...
Third step is use ngTemplateOutlet to render the template:
@Component({
selector: 'repeater',
template: `
<input type="button" value="Add" (click)="addRow()">
<div class="repeater" *ngFor="let row of repeaterArray">
<div class="repeaterRow">
<input type="button" value="Remove" (click)="removeRow(row.rowId)">
<ng-template <== this line
[ngTemplateOutlet]="itemTemplate"
[ngTemplateOutletContext]="{ $implicit: row }">
</ng-template>
</div>
</div>`
})
export class RepeaterComponent {
@Input() repeaterArray: Array<any>;
@ContentChild(TemplateRef) itemTemplate: TemplateRef<any>;
...
}
Fourth step is to use reference to the row inside TemplateRef within MasterComponent (just back to our first step):
<repeater [repeaterArray]="repeaterObj">
<template let-row>
<field-textbox [data]="row.name" [label]="'Name'"></field-textbox>
<field-textbox [data]="row.description" [label]="'Description'"></field-textbox>
</template>
</repeater>
Notice: we are passing ngOutletContext like object with $implicit property.
using the key $implicit in the context object will set it's value as default.
It works as follows:
[ngTemplateOutletContext]="{ $implicit: row }" ==> <template let-row>
[ngTemplateOutletContext]="{ item: row }" ==> <template let-row="item">
ngOutletContext is availlable only since Angular 2 version of 2.0.0-rc.2
You could try the corresponding plunkr (updated to 5.0.0)