DotNetCurry Logo

Getting Started with Web Components

Posted by: Gil Fink , on 1/29/2015, in Category HTML5 & JavaScript
Views: 18523
Abstract: Web components standard although still in development, offers a revolutionary direction for building web applications front-end in Lego style. This article gives an overview of Web Components and the four HTML5 APIs that enables you to create your own components, with an example.

Web development can be confusing and frustrating at times. Let’s consider the following scenario – you want to create a web page with some common components such as a navigation bar or a breadcrumb. A quick way to do this is to grab some boilerplate templates, for example using the Twitter Bootstrap library, or create the components on your own using a JavaScript library, for example jQuery. HTML does not support such commonly used components. HTML supports some new semantic elements that were added as part of HTML5 specifications. However HTML wasn’t extensive enough to create our own reusable components.

 

This situation has changed. In the past few months, we are hearing more and more about a new standard called Web Components. A lot of known web development experts claim that it will revolutionize the way we are creating web apps. Some of the major browser vendors are working on the Web Components polyfill libraries that can help bridge the gap between current browsers and the emerging standard. Will the standard revolutionize the way we build web apps? It definitely will, but until this standard is included in every browser, we will have to use a polyfill library.

In the article, you will get an overview of Web Components. You will get familiar with the four HTML5 APIs that enables you to create your own components and you will see a simple component implementation. At the end we will discuss the browser support and briefly discuss options to bridge the gap in browsers that do not support Web Components. But first things first, let us start by understanding what is the web components standard.

What are Web Components?

When you write traditional web applications which use server rendering engines for building web pages, you probably reuse components using custom/user controls. For example, one of the first tasks that I implemented as a novice ASP.Net developer was to create a drop down user control that was reused across an entire web site. In today’s modern web development, the rendering process is moving to the front-end and developers want to use the same custom control techniques when building the front-end. But how can a developer create his own reusable DOM element? Can we do that using HTML standards that are in practice today?

Web Components is a bundle of new standards that allow developers to build their own DOM elements. The custom elements can encapsulate common behavior and element interaction endpoints, such as custom events. A web component can also expose custom attributes that can be later used to customize the element and for setting the element’s behavior.

webcomponentslogo

A custom web component is used in a declarative way like any other HTML element. The custom elements that you create actually denote something meaningful, for example a navbar element, instead of a generic

or elements which expresses nothing. Once you go the web component way, your HTML will start to be meaningful and more robust.

Note - If you are using AngularJS, the concept of web components might sound familiar. This is because AngularJS directives use some of the concepts written in the web components standard.

The Web Components standard includes four different parts:

1. Templates

2. Imports

3. Shadow DOM

4. Custom Elements

In the next sections, we will explore each of these four parts that are included in the standard.

Templates

In the past when you wanted to create a template, you had two main options. The first option was to use a block element that would be hidden initially and displayed later when some web page interaction occurred. The problem with this option is that you fetch resources from the server, for example images, even though they might not be shown to the user. The second option was to create a script tag with an id and give it the text/template type. In that script tag, you would plant your DOM code. For example, here is how you might have created a template:


In this option the web page won’t load unnecessary resources but in order to use the template, you need to fetch the script tag element and extract its HTML. That might lead to cross-site scripting vulnerability. We can do better than that.

The new template element, which was introduced as part of the Web Components standard, enables you to define a HTML blueprint that can be later used to instantiate document fragments which include the same structure. Now you have the ability to wrap HTML content including script and style tags inside a template element and later on to use the template in your code. Here is an example of the previous script tag but now defined as a template:



In order to use the template you will have to use JavaScript. The following lines of code will fetch the template element and will import a cloned node. Later on, you would be able to append the clone into the DOM.

var template = document.querySelector('#myTemplate');
var clone = document.importNode(template.content, true);

Once the clone is appended, if the template includes script tags or style tags, they will be executed. If the template includes resources such as images or videos, they will be retrieved from the server.

One last thing that you must know about the template element is that it doesn’t support data binding. The template element as expected is a template and nothing more. We will discuss how to do data binding later on in the article.

Note – you can find the full templates documentation here: http://www.w3.org/TR/html5/scripting-1.html#the-template-element.

Imports

The new HTML5 Imports specification enables developers to load additional HTML documents without the need to use Ajax. Imports are new type of link tag. If you are a web developer you probably used the rel=”stylesheet” to specify that a link element should load a CSS file. In imports, you replace the stylesheet string with import and that’s it, the link now specifies an import. Here is an example:


In the example you can see that we are loading a HTML file called myImport.

Imports enables web developers to bundle a full component into a HTML file which might include scripts and CSS styles and later on to import that bundle in a single call. For example, if you have a component that includes JavaScript files, CSS files and more, you can bundle them into a HTML document and just import it. This option makes component writing much more powerful.

Importing a document using the import link doesn’t include its content into the web page. What it really does is to grab the document and parse it and of course load all the document’s additional resources. After the document is loaded and parsed, it is available through JavaScript. In order to access the content of an import, you need to use the link element import property. The following example shows you how to get the content from an import link element:

var content = document.querySelector('link[rel="import"]').import;

In the example, the content variable will include the whole content in memory document that the import retrieved. Once you have a reference to the document, you can use JavaScript and use its content. Let’s take a look at an example that uses both a template element and HTML5 import. Here is the template code that exists in myTemplate.html file:



Here is the document that will import the template:



  


  

In the previous code example, once the import retrieves the HTML document that includes the template, we select the element. Later on, we import a clone of the template and append it into a DIV element with a shell id. Now that we are familiar with templates and import, the next stop in the Web Components standard is the shadow DOM.

Shadow DOM

The shadow DOM specification describes how to encapsulate DOM parts such that the browser will know how to present those parts but won’t show them in the source code. That creates a boundary between the component and its user.

The concept of shadow DOM isn’t new and it is widely used by browser vendors to hide implementation details of already made components. For example, have you ever wondered how you get the control buttons of a video tag? You guessed right, this is shadow DOM in practice. Just open Chrome Developer Tools by pressing F12, go to settings and in the General tab enable the Show user agent shadow DOM. The following figure shows the configuration option:

configuring-shadow-dom

Figure 1: Enabling Chrome to Show the Shadow DOM

Once you set the configuration option, go to any web page that includes video or audio control and look at its real implementation. Here is an example of a Textarea element once you enable the shadow DOM in the browser:

shadow-dom-example

Figure 2: Textarea Element with its Shadow Root

In order to create a shadow DOM, you will have to select an HTML element and call the createShadowRoot function on it. The returned value will be a document fragment that you will be able to populate and fill with your desired content. The following source code shows how to wrap a DIV with some content inside a shadow DOM host element:

Once you created the shadow DOM root, a shadow boundary encapsulates all the root’s inner implementation. The shadow boundary prevents outer CSS to affect the inner content. More than that, it also prevents external JavaScript code to reach the wrapped content. This behavior guards the implementations from the outside world and is really useful when you want to create custom web components that aren’t affected by the hosting web page. Now that you are familiar with shadow DOM, it is time to explore the last Web Components part – custom elements.

Custom Elements

Web page development includes a lot of HTML. If you will open some web page HTML source, you will probably see large amount of DIV elements. Divs are used as block elements that wrap some content but they don’t have semantic. Instead of abusing the DIV element and using it everywhere, wouldn’t it be nicer to create an element that expresses its real meaning? This is where the custom elements specification comes in handy.

Custom elements specification enables web developers to extend HTML and to create their own custom HTML elements. The only restriction is that the new element name should include a dash and its prototype must extend the HTMLElement object. In order to create a new element, you need to register it. You will need to use the document.registerElement function which receives a mandatory name argument and an optional object that describes the new element’s prototype. If you omit the second argument, by default the custom element will inherit from HTMLElement. The following code shows how to register an element called my-element:

var myElement = document.registerElement('my-element');

The call to registerElement will explain to the browser what is the new element and return a constructor function that enables to instantiate instances of the new element.

Custom elements also enable to extend native HTML elements. The following code shows how to extend an input type:

var myInput = document.registerElement('my-input', {
  prototype: Object.create(HTMLInputElement.prototype),
  extends: 'input'
});

As you can see from the example, we pass a configuration option and state that the new element prototype is going to be the HTMLInputElement prototype. We also state that the element extends the input element. Doing that ensures that our new element extends the native one.

Once you created your new custom element, the way to use it is very simple. Just put in the HTML, a tag with the name that you gave to your custom element and you are done. The following HTML shows how to add my-input in your HTML:


Another option to create a new instance of the new custom element is by using the regular document.createElement function. Pay attention that you must register the element before you use the createElement function:

var myInput = document.registerElement('my-input', {
  prototype: Object.create(HTMLInputElement.prototype),
  extends: 'input'
});
var myInputInstance = document.createElement('my-input');
document.body.appendChild(myInputInstance);

Right now we only extended an element but we didn’t add any new behavior to the element we created. You can add new properties and functions to the custom element you created by decorating the prototype that you pass to the registerElement function. The following code shows one example of adding new property and function to the prototype of the new registered element:

var XFoo = document.registerElement('x-foo', {
  prototype: Object.create(HTMLInputElement.prototype, {
    myProperty: {
      get: function() { return 'myProperty'; }
    },
    myFunction: {
      value: function() {
        console.log('Doing something');
      }
    }
  }),
  extend: 'input'
});

In a new custom element, you can attach event handlers to a few events that are triggered during the life time of the element. For example, if you want to do something when an instance of the element is created, you can use the createdCallback event handler. Another useful event is the attributeChangedCallback that enables you to wire an event and listen for changes in attributes. The attributeChangedCallback event can be used in data binding scenarios where you want to listen to changes in attributes and act accordingly. The following example shows how to register the createdCallback function:

var myPrototype = Object.create(HTMLInputElement.prototype);
myPrototype. createdCallback = function() { 
   // Do something when an new instance of the element is created
};
var myElement = document.registerElement('my-element', { prototype: myPrototype });

Now that you are familiar with all the different parts of the Web Components specifications, we can start and building our new components.

Web Component in Action

The following example shows how to create a simple Web Component that will display an image and a caption for a team member. We will start with the code of the web component which resides in the tmpl.html file:




We start by defining the template that is going to create each team member. The template includes the HTML code and the styles that will decorate the HTML. After defining how the template looks like, we add a script that will define the custom element. Since the web component will be imported from another web page, we use the first line to get the owner document. From the owner document, we can extract the template and use it to create the shadow DOM and attach the DOM element to the hosting web page. In the createdCallback function of the web component, we set some properties to the image and the DIV elements in the template.

Now that we have our web component set, we can start importing it into our web pages. The following code shows a web page that hosts two team member elements:



    


    

Running the code will result in the following output:

running-output

Figure 3: The Result of Running the Web Page

You will be able to run this code successfully only in web components supporting browsers and that brings us to the next article section.

Web Components Polyfill Libraries

One of the larger problems that you will encounter when you want to start using Web Components is browser support. Most of the APIs that we discussed in the article aren’t supported in most of the major browsers. For example at the time of writing the article, Internet Explorer doesn’t support all Web Components APIs in none of its versions (even Internet Explorer 11). Firefox supports templates and imports but doesn’t support shadow DOM or custom elements. Chrome and Opera support all the APIs.

If you want to use tomorrow’s standards today, you should consider using a polyfill library. A polyfill library is a JavaScript library that mimics the expected browser functionality, if it doesn’t exists. The major libraries that you can use are Polymer and X-Tag. Both of the libraries include ways to create custom web components. More than that, both of the libraries come with a ready to use custom components set. In Polymer, the ready to use components are part of the library. In X-Tag you can use the Brick library. In the article, we won’t cover these libraries as they deserve a complete article of its own.

Summary

Web components standard offers a really revolutionary direction for building web applications front-end in Lego style. You can divide your web page into reusable components which include their own behavior and interaction. Later on, you can composite your page using the components that you’ve created. This is a really important direction in the way we think about how to build web applications. Even though the standard is still in development, libraries such as X-Tag and Polymer can help you get started and build your future web applications.

Download the entire source code of this article (Github)

Was this article worth reading? Share it with fellow developers too. Thanks!
Share on LinkedIn
Share on Google+
Further Reading - Articles You May Like!
Author
Gil Fink is a web development expert, ASP.Net/IIS Micrsoft MVP and the founder of sparXys. He conducts lectures and workshops for individuals and enterprises who want to specialize in infrastructure and web development. He is also co-author of several Microsoft Official Courses (MOCs) and training kits, co-author of “Pro Single Page Application Development” book (Apress) and the founder of Front-End.IL Meetup. You can get more information about Gil in his website gilfink.net


Page copy protected against web site content infringement 	by Copyscape




Feedback - Leave us some adulation, criticism and everything in between!