Custom Elements with Classes

This is an experimental technology
Because this technology's specification has not stabilized, check the compatibility table for usage in various browsers. Also note that the syntax and behavior of an experimental technology is subject to change in future versions of browsers as the specification changes.

Definition

Custom Element is a custom HTML tag and/or element that give us the tool to extend HTML's vocabulary and teaching it new tricks. It is different than normal tags as it can use lifecycle callbacks, which enable you to attach behaviors to different parts of the new element's "lifecycle." it can be built based on the general HTMLElement, or as extends of native element like <button>

Be advised that Custom Elements will be rewritten early 2016 by the W3C. It is very unlikely that any of the previous implementations will work in the future.

Advantages

The main advantages of Custom Element are:

  1. Defining/Creating new HTML/DOM elements
  2. Create elements that extend from other elements
  3. Logically bundle together custom functionality into a single tag
  4. Extend the API of existing DOM elements
  5. Very useful in Single Page Applications

Startup

In this article, we'll build custom element using the "CLASSES" introduced in JavaScript 6, AKA ( JS6 / ECMAScript 2015 / ES6).

If not ready to start working with ES6, you can refer to the prototype mentioned as per this example.

Because classes not yet supported in all browsers, we need to start our code by:

"use strict";

Then building the "class" as inherited from HTML element, and the general structure should be like:

class SaveBtn extends HTMLElement {    // You can extend any other element or Class

   constructor() {                   
      super();                         //  construct the original item to be extended, here it is the HTMLElement
   }
   
 // Define the required of the 4 available callbacks 
 // Define getters and setters
  
}

Lifecycle callbacks

You can use the following lifecycle callbacks with custom elements:

  • createdCallback - The behavior you define occurs when the element is registered.
  • attachedCallback - The behavior occurs when the element is inserted into the DOM.
  • detachedCallback - The behavior occurs when the element is removed from the DOM.
  • attributeChangedCallback - The behavior occurs when an attribute of the element is added, changed, or removed
createdCallback(){ . . } 
attachedCallback(){ . . } 
detachedCallback(){ . . } 
attributeChangedCallback() { . . }

Getters and Setters

The most condensed version of defining properties and methods is the use of get and set.

set ...{ . . } 
get ...{ . . }

The method/property value of the custom element, can be set by either of using the "data-" in the HTML file as below, or by using the "." assignment in JavaScript.

Assigning a parameter "text" for an element, using the "data-" assignment could be like:

<save-button data-text='click me'></save-button>

The same can be done using JS, by either 

myBtn.text = 'click me';
// or
myBtn.properties= {text: 'click me'}; // if the element has a a properties setter like set properties(prop){ }

See below example to see how it is done.

Create and Declare

Once done from defining callbacks, getters and setters, you need to ENABLE the element, using the  Document.registerElement() method. as below:

var MySaveBtn = document.registerElement("save-button", SaveBtn);

the element can be called/declared in the HTML file, as a new element like:

<save-button></save-button>

or can add it using the new operator in JS code like:

var myBtn = new MySaveBtn;
document.querySelector('#placeholder').appendChild(myBtn);

Style / Adding markup

Styling can be made in the createdCallback() using the this.innerHTML as below:

createdCallback(){ 
     this.innerHTML = ""+ 
         " <style> "+ " p { color: orange; } "+ " </style> "+ 
         .
         .
         + "";
}

or using the stand alone CSS file, like:

save-button > p { .. }

Example

To sum things up, below simple example, you can see it live at jsfiddle:

1. The HTML file (index.html):

<!doctype html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <title>Simple custom element using ES2015</title>
   <link rel="stylesheet" href="index.css">
</head>
<body>    
   If nothing appeared below, then your browser does not support Custom Elements.
   <save-button data-text='loaded from data-text'></save-button>
   <div id="placeholder"></div>
</body>
<script src="index.js" type="text/javascript"></script>  
</html>

2. The CSS file (index.css):

save-button > button{
   color: orangered;    
}

3. The JS file (index.js):

"use strict";
class SaveBtn extends HTMLElement {

   constructor() {
       super();
   } 
   createdCallback(){
       this.innerHTML = `
           <style> 
           p { color: orange; }
           </style>
           <p>I'm in a custom element <span id='spn' style='color:blue'></span> the below button is with me as well :).</p>
           <button id='btn'></button>
           `;
        var spn = this.querySelector('span');
        var btn = this.querySelector('button');
        btn.addEventListener('click',() => alert('The button '+btn.textContent+' had been clicked'));
   }

   attachedCallback(){
        this.querySelector('#spn').innerHTML = this.btntext != null ? this.btntext : this.dataset['text'];
        this.querySelector('#btn').textContent = this.btntext != null ? this.btntext : this.dataset['text'];
   }

   set properties(prop) {
        this.btntext = prop.text;
   }

   get text() {
        return this.textContent;
   } 
}

var MySaveBtn = document.registerElement("save-button", SaveBtn);

var myBtn = new MySaveBtn;
myBtn.properties={ text: 'Loaded from JavaScript' };  // or myBtn.text = 'click me';
document.querySelector('#placeholder').appendChild(myBtn); 

Below the live example of the above:

Specifications

Specification Status Comment
Custom Elements Working Draft  

Browsers compatibility

Chromium-based browsers are supporting an early experimental version custom elements (that will be non-standard in the future), Firefox and Safari are in the developing stage after introducing javascript 6 classes, and Microsoft Edge is considering it.

 

Spec for Custom Elements will be rewritten in early 2016. All current implementation are experimental and the upcoming standard will not be compatible with these. Web sites using Custom Elements are likely to be broken in the near future.

Document Tags and Contributors

Tags: 
 Contributors to this page: PhilTheAir, nesterran, marcoms, nkron, willwclo, dydx, teoli, hasan3ysf
 Last updated by: PhilTheAir,