Web Components – Custom Elements

custom elements web components
Mon Aug 11 2014

Custom Elements

The second piece of the Web Component puzzle are Custom Elements. To start off this post in a not so optimistic way, Custom Elements are supported at the moment by Chrome only. => http://caniuse.com/#search=custom element. This is logical since it is still in the Editor’s Draft stage by W3C => http://w3c.github.io/webcomponents/spec/custom/

Be that as it may, there are numerous polyfills and ways to make it easily compatible with most browsers. But we won’t get ahead of ourselves and see first of all what are Custom Elements.

Remember when HTML5 Semantic Elements hit the stage and everybody got really excited? => http://www.w3schools.com/html/html5_semantic_elements.asp. That was the case because we could finally break free from the “div” madness. Where we would wrap everything in divs to wrap stuff together.

So this

div_tags

 

became more like this

html5_tags

With the HTML5 tags we could write more descriptive HTML offering meaning to the data we would wrap in an element.
So viewing the markup

1. We could easily understand what is going on, as elements are more declarative.
2. Also, by giving meaning to a section like <header> we give the opportunity to the browser and various js libraries/engines e.t.c to render that area differently.

For example, below you can see a Windows Modern Application.

winrt

A short snippet of code for that desktop application is

<body>
  <div class="htmlControls fragment">
    <header aria-label="Header content" role="banner">
      <button class="win-backbutton" aria-label="Back" disabled type="button"></button>
      <h1 class="titlearea win-type-ellipsis">
        <span class="pagetitle">HTML Controls</span>
      </h1>
    </header>
    <section aria-label="Main content" role="main">
      <div class="headeredControl">
        <h2>A: Hyperlink</h2>
        <a href="http://microsoft.com">microsoft.com</a>
      </div>

We can see that we write HTML but since it is more declarative we offer more info to any library or engine that can interpret that differently. In our example the engine understands that the header is located in the <header> section and adds that part as the header of the application.The same can go for a mobile library or a javascript library concerning the various new HTML5 elements and attributes.

This is where a crazy idea comes in mind. Wouldn’t it be cool if I could create a new element? And wrap that element with certain functionality? And use it again and again on our sites?

This is where Custom Elements come in the game.

Creating your Custom Element

We’ll create together our own custom element. Before you begin however be aware it is only compatible with Chrome at the moment. In Firefox it is not enabled by default you can enable the feature by visiting about:config and enabling dom.webcomponents.enabled

So first of all I’ll add my element’s html snippet. You can check it out over here => http://bstavroulakis.com/demos/webcomponents/custom-elements/demo1.html where I’ve added some simple styling as well.

   <simple-chat>
      <chat-header>
         <chat-h-img><img src="img.png"/></chat-h-img>
         <chat-h-name>Bill</chat-h-name>
      </chat-header>
      <chat-body>
         <chat-bubble header='Bill' main='Hey there!'></chat-bubble>
         <chat-bubble header='John' main='Hi!'></chat-bubble>
      </chat-body>
      <chat-footer>
         <div class="inp-wrapper">
            <input type="" class="send_inp" />
         </div>
         <button class="send">Send</button>
      </chat-footer>
   </simple-chat>

Now we would like to attach our element to our page. This can happen by registering our element

var ChatProto = Object.create(HTMLElement.prototype);
var SimpleChat = document.registerElement('simple-chat', {
     prototype: ChatProto
   });


var BubbleProto = Object.create(HTMLElement.prototype);
var ChatBubble = document.registerElement('chat-bubble', {
     prototype: BubbleProto
   });

So after creating a prototype of HTMLElement we register our new element with that prototype.

After registering our element we’ll add some events as well to do something when the user clicks on the send button. There is a callback called “attachedCallback” where once the element is attached to our page we can add functionality to it. In the ChatProto.attachedCallback you can observe the click event listener on the send button and every time we add a bubble element that will append some html on our page as well. The final script section will look like the following.

<script type="text/javascript">
   
   var BubbleProto = Object.create(HTMLElement.prototype);
   BubbleProto.attachedCallback = function(){
      this.innerHTML = '<bubble-header>'+this.getAttribute("header")+'</bubble-header><bubble-main>'+this.getAttribute("main")+'</bubble-main>';
   }
   var ChatBubble = document.registerElement('chat-bubble', {
     prototype: BubbleProto
   });

   var ChatProto = Object.create(HTMLElement.prototype);
   ChatProto.attachedCallback = function () {
     var self = this;
     this.querySelector('.send').addEventListener('click', function(e) {
         var bubble = document.createElement("chat-bubble");
         bubble.setAttribute("header","Bill");
         bubble.setAttribute("main",self.querySelector('.send_inp').value);
         self.querySelector('.send_inp').value = '';
         self.querySelector('chat-body').appendChild(bubble);
         self.querySelector('.send_inp').focus();
     });
   }
   var SimpleChat = document.registerElement('simple-chat', {
     prototype: ChatProto
   });
</script>

And you can check the full demo at the following link => http://bstavroulakis.com/demos/webcomponents/custom-elements/demo3.html

Conclusion

1) We can now define our own DOM elements and extend other elements with them as well.
2) Add functionality to our elements in a wrapped manner.
3) Use and re-use those elements from our HTML or Javascript part or our page.

Full Stack Weekly Newsletter

A free weekly newsletter for full stack web developers!