angular2中如何动态添加克隆节点(相当于cloneNode)
How to dynamically add a cloned node in angular2 (equivalent to cloneNode)
在 Angular2 中,在某些情况下我需要复制一个节点而不是移动它。该节点具有 angular2 属性,因此 cloneNode 不起作用。我该怎么做?
*什么不起作用
let el = <HTMLElement>document.getElementById(divId);
if ((<HTMLElement>el.parentNode).id == 'itsMe')
el = <HTMLElement>el.cloneNode(true);
document.getElementById(anotherId).appendChild(el);
*什么会起作用,来自
@Component({
selector: 'my-app',
template: `
<template #temp>
<h1 [ngStyle]="{background: 'green'}">Test</h1>
<p *ngIf="bla">Im not visible</p>
</template>
<template [ngTemplateOutlet]="temp"></template>
<template [ngTemplateOutlet]="temp"></template>
`
})
export class AppComponent {
bla: boolean = false;
@ContentChild('temp') testEl: any;
}
但是如何动态添加模板呢?
让我们使用以下标记进行说明:
<p>Paragraph One</p>
<p>Paragraph Two</p> <!-- Let's try to clone this guy -->
<p>Paragraph Three</p>
选项 1 - 手动将要克隆的元素包装在 <template>
标签内
这基本上就是您所做的,只不过不是使用 ngTemplateOutlet
打印模板,而是在组件的 class 中获取对它的引用,然后使用 createEmbeddedView()
强制插入它。
@Component({
selector: 'my-app',
template: `
<p>Paragraph One</p>
<template #clone>
<p>Paragraph Two</p>
</template>
<p>Paragraph Three</p>
<button (click)="cloneTemplate()">Clone Template</button>
<div #container></div>
`
})
export class AppComponent{
// What to clone
@ViewChild('clone') template;
// Where to insert the cloned content
@ViewChild('container', {read:ViewContainerRef}) container;
constructor(private resolver:ComponentFactoryResolver){}
cloneTemplate(){
this.container.createEmbeddedView(this.template);
}
}
在此示例中,我将 "clone" 插入标记中的特定位置 (<div #container></div>
),但您也可以将其附加到当前组件模板的底部。
另请注意,原来的 <p>Paragraph Two</p>
已不可见。
选项 2 - 使用结构指令
如果您想在当前位置克隆一个元素,结果为:
<p>Paragraph One</p>
<p>Paragraph Two</p> <!-- Original paragraph -->
<p>Paragraph Two</p> <!-- Cloned paragraph -->
<p>Paragraph Three</p>
然后您可以创建结构指令 *clone
并将其应用于要克隆的段落,如下所示:
<p>Paragraph One</p>
<p *clone>Paragraph Two</p>
<p>Paragraph Three</p>
有趣的是,结构指令的作用是将它所应用的元素包装在 <template>
标记内。与我们在选项 1 中所做的非常相似,只是在那种情况下我们无法控制打印出克隆的位置(它们将出现在原始段落所在的位置)。
这基本上会复制 *ngFor
的行为,因此它可能不是很有用。另外,从您对 yurzui
的评论看来,这不是您想要的。
在 Angular2 中,在某些情况下我需要复制一个节点而不是移动它。该节点具有 angular2 属性,因此 cloneNode 不起作用。我该怎么做?
*什么不起作用
let el = <HTMLElement>document.getElementById(divId);
if ((<HTMLElement>el.parentNode).id == 'itsMe')
el = <HTMLElement>el.cloneNode(true);
document.getElementById(anotherId).appendChild(el);
*什么会起作用,来自
@Component({
selector: 'my-app',
template: `
<template #temp>
<h1 [ngStyle]="{background: 'green'}">Test</h1>
<p *ngIf="bla">Im not visible</p>
</template>
<template [ngTemplateOutlet]="temp"></template>
<template [ngTemplateOutlet]="temp"></template>
`
})
export class AppComponent {
bla: boolean = false;
@ContentChild('temp') testEl: any;
}
但是如何动态添加模板呢?
让我们使用以下标记进行说明:
<p>Paragraph One</p>
<p>Paragraph Two</p> <!-- Let's try to clone this guy -->
<p>Paragraph Three</p>
选项 1 - 手动将要克隆的元素包装在 <template>
标签内
这基本上就是您所做的,只不过不是使用 ngTemplateOutlet
打印模板,而是在组件的 class 中获取对它的引用,然后使用 createEmbeddedView()
强制插入它。
@Component({
selector: 'my-app',
template: `
<p>Paragraph One</p>
<template #clone>
<p>Paragraph Two</p>
</template>
<p>Paragraph Three</p>
<button (click)="cloneTemplate()">Clone Template</button>
<div #container></div>
`
})
export class AppComponent{
// What to clone
@ViewChild('clone') template;
// Where to insert the cloned content
@ViewChild('container', {read:ViewContainerRef}) container;
constructor(private resolver:ComponentFactoryResolver){}
cloneTemplate(){
this.container.createEmbeddedView(this.template);
}
}
在此示例中,我将 "clone" 插入标记中的特定位置 (<div #container></div>
),但您也可以将其附加到当前组件模板的底部。
另请注意,原来的 <p>Paragraph Two</p>
已不可见。
选项 2 - 使用结构指令
如果您想在当前位置克隆一个元素,结果为:
<p>Paragraph One</p>
<p>Paragraph Two</p> <!-- Original paragraph -->
<p>Paragraph Two</p> <!-- Cloned paragraph -->
<p>Paragraph Three</p>
然后您可以创建结构指令 *clone
并将其应用于要克隆的段落,如下所示:
<p>Paragraph One</p>
<p *clone>Paragraph Two</p>
<p>Paragraph Three</p>
有趣的是,结构指令的作用是将它所应用的元素包装在 <template>
标记内。与我们在选项 1 中所做的非常相似,只是在那种情况下我们无法控制打印出克隆的位置(它们将出现在原始段落所在的位置)。
这基本上会复制 *ngFor
的行为,因此它可能不是很有用。另外,从您对 yurzui
的评论看来,这不是您想要的。