Как динамически добавить клонированный узел в angular2 (эквивалентно 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);

* что будет работать, из Angular2: компонент клонирования / элемент HTML и его функциональность

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

Но как добавить шаблон динамически?

1 ответ

Решение

Давайте используем следующую разметку для иллюстрации:

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

Вариант 1 - Вручную обернуть элемент для клонирования внутри <template> тег

Это в основном то, что вы сделали, только вместо того, чтобы распечатать шаблон с ngTemplateOutlet, возьмите ссылку на него в классе вашего компонента и обязательно вставьте его 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);
    }
}

В этом примере я вставляю "клон" в определенное место в разметке (<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 что это не то, что вы хотите.

Другие вопросы по тегам