title: HTML <template> Element versus Javascript Template Literals
body: <p>Mozilla says <a href="https://developer.mozilla.org/en-US/docs/Web/Web_Components" rel="noreferrer">Web components</a> consist of three main technologies:</p>
  
  <ol>
  <li><a href="https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements" rel="noreferrer">Custom elements</a></li>
  <li><a href="https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM" rel="noreferrer">Shadow DOM</a></li>
  <li><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template" rel="noreferrer">HTML templates</a></li>
  </ol>
  
  <p>Is number 3, "HTML templates", even necessary in light of ECMAscript's <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals" rel="noreferrer">Template Literals</a>?</p>
  
  <p>Look at this example I got from <a href="https://www.sitepen.com/blog/2018/07/06/web-components-in-2018/" rel="noreferrer">James Milner</a>:</p>
  
  <pre><code>&lt;!DOCTYPE html&gt;
  &lt;html lang="en"&gt;
  &lt;head&gt;
      &lt;meta charset="UTF-8"&gt;
      &lt;meta name="viewport" content="width=device-width, initial-scale=1"&gt;
      &lt;title&gt;Web Component&lt;/title&gt;
      &lt;script type="text/javascript"&gt;
      // We define an ES6 class that extends HTMLElement
      class CounterElement extends HTMLElement{
              constructor() {
                      super();
                      // Initialise the counter value
                      this.counter = 0;
  
                      // We attach an open shadow root to the custom element
                      const shadowRoot= this.attachShadow({mode: 'open'});
  
                      // We define some inline styles using a template string
                      const styles=`
                              :host {
                                      position: relative;
                                      font-family: sans-serif;
                              }
  
                              #counter-increment, #counter-decrement {
                                      width: 60px;
                                      height: 30px;
                                      margin: 20px;
                                      background: none;
                                      border: 1px solid black;
                              }
  
                              #counter-value {
                                      font-weight: bold;
                              }
                      `;
  
                      // We provide the shadow root with some HTML
                      shadowRoot.innerHTML = `
                              &lt;style&gt;${styles}&lt;/style&gt;
                              &lt;h3&gt;Counter&lt;/h3&gt;
                              &lt;slot name='counter-content'&gt;Button&lt;/slot&gt;
                              &lt;button id='counter-increment'&gt; - &lt;/button&gt;
                              &lt;span id='counter-value'&gt; 0 &lt;/span&gt;
                              &lt;button id='counter-decrement'&gt; + &lt;/button&gt;
                      `;
  
                      // We can query the shadow root for internal elements
                      // in this case the button
                      this.incrementButton = this.shadowRoot.querySelector('#counter-increment');
                      this.decrementButton = this.shadowRoot.querySelector('#counter-decrement');
                      this.counterValue = this.shadowRoot.querySelector('#counter-value');
  
                      // We can bind an event which references one of the class methods
                      this.incrementButton.addEventListener("click", this.decrement.bind(this));
                      this.decrementButton.addEventListener("click", this.increment.bind(this));
  
              }
              increment() {
                      this.counter++
                      this.invalidate();
              }
              decrement() {
                      this.counter--
                      this.invalidate();
              }
              // Call when the counter changes value
              invalidate() {
                      this.counterValue.innerHTML = this.counter;
              }
      }
      // This is where the actual element is defined for use in the DOM
      customElements.define('counter-element', CounterElement);
      &lt;/script&gt;
  &lt;/head&gt;
  &lt;body&gt;
      &lt;counter-element&gt;&lt;/counter-element&gt;
  &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>Notice how he doesn't use an HTML template, but instead uses an ecmascript template literal to set the innerHTML of the shadowRoot.</p>
  
  <p>After this, he uses querySelector to get internal elements of the shadowRoot and he ultimately adds event listeners to the increment and decrement buttons.</p>
  
  <p>If you were to use a HTML template, instead of an ecmascript template literal, what does this gain you?</p>
  
  <p>Conceptually, I'm struggling to find a situation where I'd prefer an HTML Template Element over an Ecmascript Template Literal.</p>
  
  <p>Please advise.</p>