Angular 使用ng内容转换创建动态中继器

Angular 使用ng内容转换创建动态中继器,angular,angular2-ngcontent,Angular,Angular2 Ngcontent,我试图实现的是一个通用组件,它绑定到任意对象数组,当使用它的主组件也使用组件任意定义每行的视图时,它允许动态添加和删除行 请注意,MasterComponent是一个可以为不同页面实现的任意组件,它是自包含的,不由任何元数据或外部源定义 到目前为止,我拥有以下组件: 重复组件模板: <input type="button" value="Add" (click)="addRow()"> <div class="repeater" *ngFor="let row of repea

我试图实现的是一个通用组件,它绑定到任意对象数组,当使用它的主组件也使用组件任意定义每行的视图时,它允许动态添加和删除行

请注意,
MasterComponent
是一个可以为不同页面实现的任意组件,它是自包含的,不由任何元数据或外部源定义

到目前为止,我拥有以下组件:

重复组件模板

<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-content select="row"></ng-content>
     </div>
</div>
<repeater [repeaterArray]="repeaterObj">
    <row>
        <field-textbox [data]="row.name" [label]="'Name'"></field-textbox>
        <field-textbox [data]="row.description" [label]="'Description'"></field-textbox>
    </row>
</repeater>
这种方法有两个问题,我似乎找不到解决方案

  • ngFor
    复制模板时,所有行的
    ng content
    选择器都是相同的,在渲染后只剩下一个
    ng content
    转换点
  • transcluded指令中,
    ngFor
    声明中没有对
    变量的引用,因此无法正确绑定数据
  • 有没有更好的方法来实现
    RepeaterComponent
    ,让我尽可能少地创建更多不同任意结构和不同模板的新
    MasterComponents

    以下是实现动态中继器的步骤:

    第一步是提供
    TemplateRef
    作为
    RepeaterComponent
    的子元素:

    <repeater [repeaterArray]="repeaterObj">
      <ng-template>
        ...
      </ng-template>
    </repeater>
    
    第三步是使用
    ngTemplateOutlet
    呈现模板:

    @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>;
      ...
    }
    
    注意:我们正在传递带有
    $implicit
    属性的
    ngOutletContext
    like对象

    在上下文对象中使用$implicit键将其值设置为 默认

    其工作原理如下:

    [ngTemplateOutletContext]="{ $implicit: row }"  ==> <template let-row>
    
    [ngTemplateOutletContext]="{ item: row }"       ==> <template let-row="item">
    
    [ngTemplateOutletContext]=“{$implicit:row}”==>
    [ngTemplateOutletContext]=“{item:row}”==>
    
    ngOutletContext
    仅在2.0.0-rc.2的Angular 2版本之后可用


    您可以尝试相应的(更新为5.0.0

    看起来这正是我想要的,谢谢!唯一一件似乎没有按预期工作的事情是使用[(ngModel)]对字段textbox组件进行双向绑定。下面演示了在尝试使用相同绑定更改两个不同的输入字段时出现的问题。在应用程序组件模板中,您可以看到正常的
    绑定按预期工作,并更新对象绑定,但更改文本框不会将绑定应用回对象。请尝试使用
    EventEmitter
    实现双向绑定,就像Yep一样,这是可行的。我希望绑定能够正确传播,而不必在组件上实现双向绑定,尽管在使用[ngTemplateOutlet]的模板之外使用绑定时也可以正常工作。这与不使用ngTemplateOutlet的行为相同。ngTemplateOutlet并不是一个魔术。它只是在TemplateRefAh中传递数据,你是对的。我在考虑绑定到已定义的类实例,而不是绑定到JSON属性。再次感谢!
    @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>;
      ...
    }
    
    <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>
    
    [ngTemplateOutletContext]="{ $implicit: row }"  ==> <template let-row>
    
    [ngTemplateOutletContext]="{ item: row }"       ==> <template let-row="item">