Creating a dynamic repeater with ng-content transclusion

前端 未结 1 411
独厮守ぢ
独厮守ぢ 2020-12-03 08:45

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

相关标签:
1条回答
  • 2020-12-03 09:33

    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)

    0 讨论(0)
提交回复
热议问题