How to dynamically add a cloned node in angular2 (equivalent to cloneNode)

笑着哭i 提交于 2019-12-01 09:08:19

问题


In Angular2, I need to duplicate a node rather than moving it in some cases. That node has angular2 properties so cloneNode doesn't work. How can I do it?

*what doesn't work

    let el = <HTMLElement>document.getElementById(divId);
    if ((<HTMLElement>el.parentNode).id == 'itsMe')
        el = <HTMLElement>el.cloneNode(true);
    document.getElementById(anotherId).appendChild(el);

*what would work, from Angular2: Cloning component / HTML element and it's functionality

@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;
} 

But how to add a template dynamically?


回答1:


Let's use the following markup for illustration:

<p>Paragraph One</p>
<p>Paragraph Two</p>   <!-- Let's try to clone this guy -->
<p>Paragraph Three</p>

Option 1 - Manually wrap the element to clone inside a <template> tag

This is basically what you did, only instead of printing out the template with ngTemplateOutlet, grab a reference to it in your component's class and insert it imperatively with 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);
    }
}

In this example, I'm inserting the "clone" at a specific location in the markup (<div #container></div>), but you could also append it at the bottom of the current component's template.

Also note that the original <p>Paragraph Two</p> is no longer visible.

Option 2 - Use a structural directive

If you want to clone an element at its current location, ending up with:

<p>Paragraph One</p>
<p>Paragraph Two</p>   <!-- Original paragraph -->
<p>Paragraph Two</p>   <!-- Cloned paragraph   -->
<p>Paragraph Three</p>

Then you could create a structural directive *clone and apply it to the paragraph to clone, like this:

<p>Paragraph One</p>
<p *clone>Paragraph Two</p>
<p>Paragraph Three</p>

Interestingly, what a structural directive does is wrap the element it is applied to inside a <template> tag. Pretty similar to what we did in option 1, only in that case we have NO CONTROL over the location where the clones are printed out (they will appear where the original paragraph was).

This would essentially replicate *ngFor's behavior so it's probably not very useful. Also, it seems from your comment to yurzui that it's not what you want.



来源:https://stackoverflow.com/questions/41918325/how-to-dynamically-add-a-cloned-node-in-angular2-equivalent-to-clonenode

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!