加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

使用Angular2创建具有ng-content transclusion的动态转发器

发布时间:2020-12-17 06:48:42 所属栏目:安全 来源:网络整理
导读:我想要实现的是一个通用组件,它绑定到一个任意对象数组,当每个行的视图也由使用它的主组件任意定义组件时,允许动态添加和删除行. 请注意,MasterComponent是一个任意组件,可以为不同的页面实现,并且是自包含的,不是由任何元数据或外部源定义的. 到目前为止我
我想要实现的是一个通用组件,它绑定到一个任意对象数组,当每个行的视图也由使用它的主组件任意定义组件时,允许动态添加和删除行.

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

到目前为止我所拥有的是以下组件:

RepeaterComponent模板:

<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>

MasterComponent模板:

<repeater [repeaterArray]="repeaterObj">
    <row>
        <field-textbox [data]="row.name" [label]="'Name'"></field-textbox>
        <field-textbox [data]="row.description" [label]="'Description'"></field-textbox>
    </row>
</repeater>

< field-textbox> component是一个自定义组件,用于封装包含我需要使用的其他数据的简单输入.

MasterComponent包含一个对象,对于此实例,它看起来像这样:

repeaterObj = [
{
    "rowId": 1,"name": "First brand","description": "First description"
},{
    "rowId": 2,"name": "Second brand","description": "Second description"
},{
    "rowId": 3,"name": "Third brand","description": "Third description"
}
];

这种方法有两个我似乎无法找到解决方案的问题.

>当ngFor复制模板时,ng-content选择器对于所有行都是相同的,这使得渲染后只有一个ng-content transclusion点.
>< field-textbox>中没有引用ngFor声明中的行变量. transcluded指令,所以我无法正确绑定数据.

有没有更好的方法来实现RepeaterComponent,这将给我最少的努力来创建更多不同任意结构和不同模板的新MasterComponents?

解决方法

您可以使用 ngTemplateOutlet来实现它.

以下是实施动态转发器的步骤:

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

<repeater [repeaterArray]="repeaterObj">
  <ng-template>
    ...
  </ng-template>
</repeater>

第二步是通过ContentChild在RepeaterComponent中查询此模板:

export class RepeaterComponent { 
  @ContentChild(TemplateRef) itemTemplate: TemplateRef<any>;
  ...

第三步是使用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>;
  ...
}

第四步是使用对MasterComponent中TemplateRef内部行的引用(刚回到我们的第一步):

<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>

注意:我们使用$implicit属性传递类似于对象的ngOutletContext.

using the key $implicit in the context object will set it’s value as
default.

它的工作原理如下:

[ngTemplateOutletContext]="{ $implicit: row }"  ==> <template let-row>

[ngTemplateOutletContext]="{ item: row }"       ==> <template let-row="item">

ngOutletContext仅在角色版本2.0.0-rc.2之后可用

您可以尝试相应的plunkr(更新到5.0.0)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读