> For the complete documentation index, see [llms.txt](https://lochiwei.gitbook.io/web/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://lochiwei.gitbook.io/web/component/template.md).

# \<template>

[web](/web/master.md) ⟩ [component](/web/component.md) ⟩ \<template>

{% hint style="info" %}
🚧
{% endhint %}

{% tabs %}
{% tab title="👥 相關" %}

* [Custom Events](/web/browser/event/custom.md) ⟩ [Element-defined Content](/web/component/custom-element/content.md)
* [DOM hierarchy](/web/browser/dom/hierarchy.md)
* [content](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTemplateElement/content) of <mark style="color:purple;">**`<template>`**</mark> is a [DocumentFragment](/web/browser/dom/type/documentfragment.md).
* 可將 <mark style="color:purple;">**`<template>`**</mark> 放在[靜態屬性](/web/js/val/class/member/static.md)中，詳情： :point\_right: [init static property](/web/js/val/class/member/static/init.md)
  {% endtab %}

{% tab title="⭐️ 重點" %}
{% hint style="info" %}
[\<template>](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template) tags (and their <mark style="color:yellow;">**children**</mark>)：&#x20;

* <mark style="color:red;">**never**</mark> <mark style="color:yellow;">**rendered**</mark> by web browser.
* only useful on web pages that use <mark style="color:yellow;">**JavaScript**</mark>.
* [template.content](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTemplateElement/content) is a [DocumentFragment](/web/browser/dom/type/documentfragment.md).
* can be **cloned** by template.[content](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTemplateElement/content).[cloneNode()](https://developer.mozilla.org/en-US/docs/Web/API/Node/cloneNode).&#x20;
  {% endhint %}

{% hint style="warning" %}

* when cloning/inserting [template.content](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTemplateElement/content) into document, the [fragment](/web/browser/dom/type/documentfragment.md) itself will <mark style="color:red;">**not**</mark> be inserted, but its <mark style="color:yellow;">**children**</mark> will.
  {% endhint %}

{% hint style="info" %}
Use a <**template**> element to **clone** DOM, instead of setting **shadowRoot.innerHTML**. \
👉 [Custom Elements](/web/component/custom-element.md) ⟩ [Element-defined Content](/web/component/custom-element/content.md)
{% endhint %}
{% endtab %}

{% tab title="📗 參考" %}

* [ ] [\<template> element](https://javascript.info/template-element) - js.info
  {% endtab %}

{% tab title="📘 手冊" %}

* 📘 [Using templates and slots](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_templates_and_slots)
  * [Using templates with web components](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_templates_and_slots#using_templates_with_web_components)
* [\<template>](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template)
* [Node](/web/browser/dom/type/node.md) ⟩ [.cloneNode()](https://developer.mozilla.org/en-US/docs/Web/API/Node/cloneNode)
* 📘 [DocumentFragment](https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment)
* [HTMLTemplateElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTemplateElement)
  * .[content](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTemplateElement/content) ([DocumentFragment](https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment))
    {% endtab %}
    {% endtabs %}

## HTML templates examples

{% tabs %}
{% tab title="1️⃣" %}
:floppy\_disk: [replit.com](https://replit.com/@pegasusroe/web-component-error-message#script.js)

{% hint style="info" %}

* can put <mark style="color:blue;">`<style>`</mark> and <mark style="color:blue;">`<script>`</mark> into <mark style="color:blue;">`<template>`</mark> as well.
  {% endhint %}

```markup
<!-- styles and scripts in template -->
<template>

  <style>
    p { font-weight: bold; }
  </style>
  
  <script>
    alert("Hello");
  </script>
  
</template>
```

{% endtab %}

{% tab title="2️⃣" %}
{% hint style="info" %}

* content **becomes live** (styles apply, scripts run etc) when **inserted** into **document**.
  {% endhint %}

```markup
<!-- template -->
<template id="tmpl">
  <script>
    console.log("Hello");
  </script>
  <div class="message">Hello, world!</div>
</template>

<!-- script -->
<script>

  let div = document.createElement('div');

  // ⭐️ clone template content
  //    tmpl            : HTMLTemplateElement
  //    tmpl.content    : DocumentFragment
  //    node.cloneNode(): Node (return type)
  div.append(tmpl.content.cloneNode(true));

  // ⭐️ inserted into document
  // ⭐️ now script (from <template>) runs
  document.body.append(div);    
  
</script>
```

{% endtab %}

{% tab title="3️⃣" %}
{% hint style="info" %}

* we can use `<template>` to **populate** [shadow root](/web/component/shadow-dom/shadow-root.md).&#x20;
  {% endhint %}

📁 script.js  👉 [replit](https://replit.com/@pegasusroe/use-template-to-populate-shadow-root#script.js)

```javascript
div.onclick = function() {

    // attach shadow root to <div> (shadow host)
    let root = div.attachShadow({mode: 'open'});

    // clone template content (<style>, <p>)
    let clonedContent = tmpl.content.cloneNode(true);

    // append to shadow root
    // ⭐️ 注意：light DOM (text node: "Click me") 被 shadow DOM 取代了❗️
    root.append(clonedContent);

    let p = root.$('#message');
    p.innerHTML = "Hello from the shadows❗️";
}; 
```

📁 index.html

```markup
<!-- ⭐️ template -->
<template id="tmpl">
	<style>
		p {
			font-weight: bold;
                margin: 0 auto;
		}
	</style>
	<p id="message"></p>
</template>

<!-- shadow host -->
<div id="div">Click me❗️</div>

<!-- scripts -->
<script src="helpers.js"></script>
<script src="script.js"></script>
```

👉 [helpers.js](/web/browser/dom/querying-elements/dom.md)
{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="HTML" %}

```markup
<!-- web component -->
<my-component>
  a "none" error message
</my-component>

<my-component kind="warning">
  this is a warning
</my-component>

<my-component kind="error">
  this is an error message
</my-component>
```

{% endtab %}

{% tab title="JS" %}

```javascript
// ⭐️ 1. custom web component
class MyComponent extends HTMLElement {

    // constructor
    constructor() {

        // tell HTMLElement to initialize itself.
        super();

    }

    // choose which template to use
    connectedCallback() {

        // create <div> elements
        this.templates = document.createElement('div');
        this.container = document.createElement('div');

        // ⭐️ add a shadow DOM to component
        //    to activate/deactivate templates
        this.root = this.attachShadow({mode: 'open'});
        this.root.appendChild(this.templates); 
        this.root.appendChild(this.container);

        // fill in templates
        this.templates.innerHTML = MyComponent.template(); 
        
        // choose which template to use
        const kind = this.getAttribute(`kind`) || `none`;
        const template = this.templates.querySelector(`template.${kind}-type`); 
        
        if (template) {
            const clone = template.content.cloneNode(true);
            this.container.innerHTML = '';
            this.container.appendChild(clone); 
        }

    }

    // template HTML
    static template() {

        // 3 templates
        // - template.warning-type
        // - template.error-type
        // - template.none-type
        return ` 
            <template class="warning-type">
                <style> 
                    .warning { 
                        background-color: yellow; 
                        padding: 15px; 
                        color: red; 
                    } 
                </style>

                <div class="warning">
                    <slot>Error component<slot> 
                </div> 
            </template>

            <template class="error-type">
                <style>
                    .error { 
                        background-color: red; 
                        padding: 15px; 
                        color: yellow; 
                    }
                </style>

                <div class="error">
                    <slot>Error component<slot> 
                </div> 
            </template>

            <template class="none-type">
                <style> 
                    .none { 
                        background-color: gray; 
                        padding: 15px; 
                        color: #eee; 
                    } 
                </style>

                <div class="none">
                    <slot>Error component<slot> 
                </div> 
            </template>
        `;
    }
} 

// ⭐️ 2. custom tag <my-component>
// ⭐️⭐️ custom element names must contain a "hyphen".
customElements.define('my-component', MyComponent);
```

{% endtab %}

{% tab title="codepen" %}
{% embed url="<https://codepen.io/lochiwei/pen/yLXOrVm>" %}

{% endtab %}
{% endtabs %}
