1

I'm trying to use a template tag inside an Angular component.

Following the MDN example I created a similar stackblitz example.

In the original example, the template tag has no children but it's content has children. On my example it's the other way around. The template has the children and content is empty (open the console and click the button to see it).

As a result, trying to manipulate the cloned template content fails.

What am I doing wrong?


app.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  name = 'Angular';

  click() {
    const template: HTMLTemplateElement = document.querySelector('#t');
    console.log(`template.childElementCount: ${template.childElementCount}`);
    console.log(`template.content.childElementCount: ${template.content.childElementCount}`);
    const content = document.importNode(template.content, true);
    console.log(content.querySelector('.c2'));
  }
}

app.component.html

<button (click)="click()">test</button>
<template id="t">
    <div class="c1">
        <div class="c2">{{ name }}</div>
    </div>
</template>

Console result

enter image description here

Oram
  • 1,589
  • 2
  • 16
  • 22

2 Answers2

0

You should only call template and not template.contentas first argument.

const content = document.importNode(template, true);
console.log(content.querySelector('.c2'));

enter image description here

Matt Walterspieler
  • 2,073
  • 2
  • 21
  • 34
  • Can you explain the difference? – Oram Aug 27 '19 at 14:40
  • In the documentation example, a whole node is set as the first argument. https://developer.mozilla.org/en-US/docs/Web/API/Document/importNode#Example But I agree with you it should accept an argument of type DocumentFragment. – Matt Walterspieler Aug 27 '19 at 15:10
  • The example you mention doesn't help as it doesn't involve a template tag. It just clones some node... – Oram Aug 28 '19 at 05:09
0

Turns out there is an open bug about this: https://github.com/angular/angular/issues/15557

As a workaround I created the template with createElement.

const name = "answer";
const template = document.createElement('template');
template.innerHTML = `<div class="c1"><div class="c2">${name}</div></div>`;
console.log(`template.childElementCount: ${template.childElementCount}`);
console.log(`template.content.childElementCount: ${template.content.childElementCount}`);
const content = document.importNode(template.content, true);
console.log(content.querySelector('.c2'));
Oram
  • 1,589
  • 2
  • 16
  • 22