web components

shadow dom, custom elements, <template>, <slot>, attributes and properties, life cycles, custom events

by AbdallaNayer

HTML

<!--Custom Element Template-->
<template id="rating-dots">
    <style>
        .rating-dots__dot{
            border: 1px solid grey; border-radius: 50%;
            width: 16px;height: 16px;display: inline-block;
        }
        .rating-dots__dot__selected{background: green}
        h2{color: grey;}
    
    </style>
    <div class="rating-dots">
        <span class="rating-dots__dot"></span>
        <span class="rating-dots__dot"></span>
        <span class="rating-dots__dot"></span>
        <span class="rating-dots__dot"></span>
        <span class="rating-dots__dot"></span>
    </div>
    <slot name="rating-details"></slot><!--Placeholder for user markup-->
    <h2 class="caption"></h2> <!--Should be Passed by the user-->
</template>

<!--Custom Element Class -->
<script>
  class RatingDots extends HTMLElement {
    constructor() {
      super();
      //custom element template
      let tpl = document.querySelector('#rating-dots');
      // mode values: 'open', 'closed'
      let shadowRoot = this.attachShadow({
        mode: 'open'
      });
      //appends the template into custom element
      shadowRoot.appendChild(tpl.content.cloneNode(true));
      this.ratingDots = this.shadowRoot.querySelector('.rating-dots');
    }

    /*getters and setters for properties 
    which updates the corresponding attributes*/
    get rating() {
      return this.getAttribute('rating');
    }

    set rating(val) {
      this.setAttribute('rating', val || 0);
    }

    get caption() {
      return this.getAttribute('caption');
    }

    set caption(val) {
      this.setAttribute('caption', val || '');
    }

    //Called every time the element is inserted into the DOM
    connectedCallback() {
      this.initDots();
      this.ratingDots.addEventListener('click', this._onClick.bind(this));
    }

    disconnectedCallback() {
      this.ratingDots.removeEventListener('click', this._onClick.bind(this));
    }
    //attributeChangedCallback called only for observed...