Web-Components #102 - 5 more lessons after learning Web Components #101
Tags: webcomponents, javascript, webdev, showdev
Published: 2021-05-22 13:25:48

---
title: Web-Components #102 - 5 more lessons after learning Web Components #101
published: true
description: The obligatory 5 things that make developing Web Components easier
tags: webcomponents,javascript,webdev,showdev
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ahxs2zr210pbsmex68g2.png
---

## Standing on the shoulders of giants

I learned as much as I could on Web Components development since 2016.  And I am still learning.

**Credit where credit is due!**

I could not have gotten this far without the [_answers_ on StackOverflow](https://stackoverflow.com/questions/tagged/native-web-component%2bor%2bweb-component%2bor%2bcustom-element%2bor%2bshadow-dom%2bor%2bcustom-component%2b-reactjs?tab=Newest), the [_discussions_ on GitHub](https://github.com/WICG/webcomponents/issues) and [the _blogs_ from early-adopters](https://www.google.com/search?q=web+components+mdn&sxsrf=ALeKk02kTQR5p4ax1xL-v1VQ8kUMfAbDJg%3A1621688799686&source=lnt&tbs=cdr%3A1%2Ccd_min%3A1-1-2011%2Ccd_max%3A1-1-2018&tbm=)¹.

¹) Old blogs can refer to **V0** Web Component technologies not available in the current **V1** standard

<hr>

# 5 lessons to make your Web Component code better

* Most (early) examples showed all **three** Web Component technologies in one code example

  * templates
  * shadowDOM
  * custom Elements API

  **Each can be used without the other**:

  * 📝 You can use templates for any block of _inert_ HTML

  * 📝 You can assign shadowDOM to regular HTML Elements

  * 📝 You can create **Custom Elements** _without_ templates or shadowDOM

<hr>

## 🦄 1. &lt;template>

* creates _**inert**_ HTML snippets, where previously you would have used: 
  ```html
  <script type="application/html">...</script>
    or
  <div style="display:none">...</div>
  ```

* Templates are parsed when you use ``template.content.cloneNode(true)``

* If you use _template content_ **once**, you can **skip** the ``.cloneNode(true)`` part


* Do not use a ``<template>`` just because most (early) blogs show: 
  ```js
  let template = document.createElement("template");
  template.innerHTML = ` CSS & HTML CONTENT `;
  this.shadowRoot.innerHTML = template.innerHTML;
  ```

  This **is** a very expensive way of writing:

  ```js
  this.shadowRoot.innerHTML = ` CSS & HTML CONTENT `;
  ```

* My personal preference, when I do use/need Templates, is to keep ``<template>s`` in the ``<head>`` of the document.

  * They load early
  * My IDE does all syntax highlighting
  * I use ``id="UPPERCASE"`` so they stand out, and the ``<my-element>`` can have a _generic_ statement: ``document.getElementById(this.nodeName)`` to read the ``<template>``


    ```html

      <template id="MY-ELEMENT">
        <style>
          :host { ... }
        </style>
        <div><slot><slot></div>
      </template>

    ```

     Use ``this.localeName`` for lowercase notation ``id="my-element"``

<hr>

## 🦄 2. super()

* ``super()`` **sets** _and_ **returns** the `this` scope.

  ```js
  constructor() {
    super();
    this.title = "Web Components 102";
  }
  ```

  can be written as:

  ```js
  constructor() {
    super().title = "Web Components 102";
  }
  ```

<hr>

## 🦄 3. always call super() first in constructor

* Now you understand ``super()``, you _may_ question the comment many copy [from the MDN documentation](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements) and [early blogs](https://medium.com/dev-channel/the-case-for-custom-elements-part-1-65d807b4b439):

  ```js
  constructor() {
    // Always call super first in constructor
    super();
    // Element functionality written in here
  }
  ```

  What they _meant_ to say was:

  ```js
  constructor() {
    // You can *not* reference 'this' *before* it is created by super();
    // It is valid to use *any other* JavaScript *before* super()
    const template = () => document.getElementById(this.nodeName);
    super().append( template().content.cloneNode(true) );
  }
  ```

  ‼️ Note: ``template()`` is a function, it is called **_after_** ``super()`` created the 'this' scope. So ``this.nodeName`` works

<hr>

## 🦄 4. attachShadow

* ``attachShadow``  **sets** _and_ **returns** ``this.shadowRoot``

  So there is **no need** to create your own property: 

  ```js
    this.shadow = this.attachShadow({mode:"open"});
  ```

  ```js
  constructor(){
      super();
      this.attachShadow({mode:"open"});
      this.shadowRoot.innerHTML = `...`;
  }
  ```
  can all be _chained_:
  ```js
  constructor(){
      super() // sets AND returns 'this'
        .attachShadow({mode:"open"}) // sets AND returns this.shadowRoot
        .innerHTML = `...`;
  }
  ```
* note: ``attachShadow({mode:"closed"})`` does **not** set ``this.shadowRoot``; preventing users from accessing your components shadowRoot. You will hardly see ``closed`` being used *in the wild*

<hr>

## 🦄 5. appendChild vs. append

* **IE11** did not have the ``el.append(nodes)`` method; maybe that is why so many developers stick to ``appendChild``

* ``el.appendChild(element)`` - [MDN appendChild documentation](https://developer.mozilla.org/en-US/docs/Web/API/Node/appendChild)

    appends **one** ``element``, and returns the ``element`` reference

* ``el.append(nodes)`` - [MDN append documentation](https://developer.mozilla.org/en-US/docs/Web/API/Element/append)

    appends all nodes (text nodes & elements), and returns _nothing_

    ``append`` does **not** _parse_ HTML, like ``.innerHTML`` and ``.insertAdjacentHTML`` do

* When you **do not** need the appendChild _return_ value; you can rewrite:

    ```js
      super();
      const shadow = this.attachShadow({mode: 'open'});
      this.div = document.createElement('div');
      this.style = document.createElement('style');
      shadow.appendChild(style);
      shadow.appendChild(div);
    ```

    to:

    ```js
      super()
          .attachShadow({mode: 'open'})
          .append( 
                  this.div   = document.createElement('div')  ,
                  this.style = document.createElement('style')
                 );
    ```

##  🦄 Make that 6 

See: https://dev.to/dannyengelman/web-component-developers-do-not-connect-with-the-connectedcallback-yet-4jo7

##  🦄 Or 7 

[#103 Dear Web Component](https://dev.to/dannyengelman/dear-web-component-1m51)

<br>
<hr>
<br>
Thank your for reading:  
**Web-Components #102 - 5 more lessons after learning Web Components #101**

{% jsfiddle https://jsfiddle.net/WebComponents/62f1eLay result,html,js %}