javascripthtmlblazorhtml-templates

Why can I not interact with an HTML <template> element rendered by Blazor?


Normally, if I have an el: HTMLTemplateElement, I can use el.innerHTML or el.content.firstElementChild to access its content. However, in this case, this template is rendered by Blazor and somehow all the content is inside a #document-fragment and I cannot access it:

enter image description here

Strangely enough, only textContent produces the text I want although normally it does not work on <template> (see the below code snippet for "normal" behavior).

What's happening here? How does Blazor make such a strange template element? I made sure the tag is actually HTMLTemplateElement and is not a Custom Element.

const template = document.querySelector("template");
console.log(template.innerHTML);
console.log(template.content.firstElementChild);
console.log(template.textContent);
<template><div>Hello</div></template>

The Blazor code:

<template data-markdown="true" style="display: none !important;">
    <div>
        @(ChildContent)
    </div>
</template>

@code {

    [Parameter]
    public RenderFragment? ChildContent { get; set; }
}

Solution

  • I finally found out the issue. Blazor does not simply print the HTML content, it attaches children element (probably using appendChild). The same behavior can be seen when we use appendChild on an HTMLTemplateElement:

    enter image description here

    const t = document.querySelector("template");
    const myDiv = document.createElement("div");
    myDiv.innerHTML = "Hello there!";
    
    t.appendChild(myDiv);
    
    console.log(t.innerHTML);
    console.log(t.textContent);
    console.log(t.firstElementChild);
    console.log(t.content.firstElementChild);
    <template></template>

    A correct attempt should be:

    const t = document.querySelector("template");
    const myDiv = document.createElement("div");
    myDiv.innerHTML = "Hello there!";
    
    t.content.appendChild(myDiv);
    
    console.log(t.innerHTML);
    console.log(t.textContent);
    console.log(t.firstElementChild);
    console.log(t.content.firstElementChild);
    <template></template>