16 min read

In this article by Sandeep Kumar Patel, author of the book Learning Web Component Development, we will learn about the web component specification in detail. Web component is changing the web application development process. It comes with standard and technical features, such as templates, custom elements, Shadow DOM, and HTML Imports.

The main topics that we will cover in this article about web component specification are as follows:

  • What are web components?
  • Benefits and challenges of web components
  • The web component architecture
  • Template element
  • HTML Import

(For more resources related to this topic, see here.)

What are web components?

Web components are a W3C specification to build a standalone component for web applications. It helps developers leverage the development process to build reusable and reliable widgets. A web application can be developed in various ways, such as page focus development and navigation-based development, where the developer writes the code based on the requirement. All of these approaches fulfil the present needs of the application, but may fail in the reusability perspective. This problem leads to component-based development.

Benefits and challenges of web components

There are many benefits of web components:

  • A web component can be used in multiple applications. It provides interoperability between frameworks, developing the web component ecosystem. This makes it reusable.
  • A web component has a template that can be used to put the entire markup separately, making it more maintainable.
  • As web components are developed using HTML, CSS, and JavaScript, it can run on different browsers. This makes it platform independent.
  • Shadow DOM provides encapsulation mechanism to style, script, and HTML markup. This encapsulation mechanism provides private scope and prevents the content of the component being affected by the external document.

Equally, some of the challenges for a web component include:

  • Implementation: The W3C web component specification is very new to the browser technology and not completely implemented by the browsers.
  • Shared resource: A web component has its own scoped resources. There may be cases where some of the resources between the components are common.
  • Performance: Increase in the number of web components takes more time to get used inside the DOM.
  • Polyfill size: The polyfill are a workaround for a feature that is not currently implemented by the browsers. These polyfill files have a large memory foot print.
  • SEO: As the HTML markup present inside the template is inert, it creates problems in the search engine for the indexing of web pages.

The web component architecture

The W3C web component specification has four main building blocks for component development. Web component development is made possible by template, HTML Imports, Shadow DOM, and custom elements and decorators. However, decorators do not have a proper specification at present, which results in the four pillars of web component paradigm. The following diagram shows the building blocks of web component:

These four pieces of technology power a web component that can be reusable across the application. In the coming section, we will explore these features in detail and understand how they help us in web component development.

Template element

The HTML <template> element contains the HTML markup, style, and script, which can be used multiple times. The templating process is nothing new to a web developer. Handlebars, Mustache, and Dust are the templating libraries that are already present and heavily used for web application development. To streamline this process of template use, W3C web component specification has included the <template> element.

This template element is very new to web development, so it lacks features compared to the templating libraries such as Handlebars.js that are present in the market. In the near future, it will be equipped with new features, but, for now, let’s explore the present template specification.

Template element detail

The HTML <template> element is an HTMLTemplateElement interface. The interface definition language (IDL) definition of the template element is listed in the following code:

interface HTMLTemplateElement : HTMLElement {
readonly attribute DocumentFragment content;
};

The preceding code is written in IDL language. This IDL language is used by the W3C for writing specification. Browsers that support HTML Import must implement the aforementioned IDL. The details of the preceding code are listed here:

  • HTMLTemplateElement: This is the template interface and extends the HTMLElement class.
  • content: This is the only attribute of the HTML template element. It returns the content of the template and is read-only in nature.
  • DocumentFragment: This is a return type of the content attribute. DocumentFragment is a lightweight version of the document and does not have a parent.

To find out more about DocumentFargment, use the following link:

https://developer.mozilla.org/en/docs/Web/API/DocumentFragment

Template feature detection

The HTML <template> element is very new to web application development and not completely implemented by all browsers. Before implementing the template element, we need to check the browser support. The JavaScript code for template support in a browser is listed in the following code:

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>
Web Component: template support
</title>
</head>
<body>
<h1 id="message"></h1>
<script>
var isTemplateSupported = function () {
var template = document.createElement("template");
return 'content' in template;
};
var isSupported = isTemplateSupported(),
message = document.getElementById("message");
if (isSupported) {
message.innerHTML = "Template element is supported by the
browser.";
} else {
message.innerHTML = "Template element is not supported by
the browser.";
}
</script>
</body>
</html>

In the preceding code, the isTemplateSupported method checks the content property present inside the template element. If the content attribute is present inside the template element, this method returns either true or false. If the template element is supported by the browser, the h1 element will show the support message. The browser that is used to run the preceding code is Chrome 39 release. The output of the preceding code is shown in following screenshot:

The preceding screenshot shows that the browser used for development is supporting the HTML template element.

There is also a great online tool called “Can I Use for checking support for the template element in the current browser. To check out the template support in the browser, use the following link:

http://caniuse.com/#feat=template

The following screenshot shows the current status of the support for the template element in the browsers using the Can I Use online tool:

Inert template

The HTML content inside the template element is inert in nature until it is activated. The inertness of template content contributes to increasing the performance of the web application. The following code demonstrates the inertness of the template content:

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>
Web Component: A inert template content example.
</title>
</head>
<body>
<div id="message"></div>
<template id="aTemplate">
<img id="profileImage"
src="http://www.gravatar.com/avatar/
c6e6c57a2173fcbf2afdd5fe6786e92f.
png">
<script>
alert("This is a script.");
</script>
</template>
<script>
(function(){
var imageElement =
document.getElementById("profileImage"),
messageElement = document.getElementById("message");
messageElement.innerHTML = "IMG element "+imageElement;
})();
</script>
</body>
</html>

In the preceding code, a template contains an image element with the src attribute, pointing to a Gravatar profile image, and an inline JavaScript alert method. On page load, the document.getElementById method is looking for an HTML element with the #profileImage ID. The output of the preceding code is shown in the following screenshot:

The preceding screenshot shows that the script is not able to find the HTML element with the profileImage ID and renders null in the browser. From the preceding screenshot it is evident that the content of the template is inert in nature.

Activating a template

By default, the content of the <template> element is inert and are not part of the DOM. The two different ways that can be used to activate the nodes are as follows:

  • Cloning a node
  • Importing a node

Cloning a node

The cloneNode method can be used to duplicate a node. The syntax for the cloneNode method is listed as follows:

<Node> <target node>.cloneNode(<Boolean parameter>)

The details of the preceding code syntax are listed here:

  • This method can be applied on a node that needs to be cloned.
  • The return type of this method is Node.
  • The input parameter for this method is of the Boolean type and represents a type of cloning. There are 2 different types of cloning, listed as follows:
    • Deep cloning: In deep cloning, the children of the targeted node also get copied. To implement deep cloning, the Boolean input parameter to cloneNode method needs to be true.
    • Shallow cloning: In shallow cloning, only the targeted node is copied without the children. To implement shallow cloning the Boolean input parameter to cloneNode method needs to be false.

The following code shows the use of the cloneNode method to copy the content of a template, having the h1 element with some text:

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>
Web Component: Activating template using cloneNode method
</title>
</head>
<body>
<div id="container"></div>
<template id="aTemplate">
<h1>Template is activated using cloneNode method.</h1>
</template>
<script>
var aTemplate = document.querySelector("#aTemplate"),
container = document.getElementById("container"),
templateContent = aTemplate.content,
activeContent = templateContent.cloneNode(true);
container.appendChild(activeContent);
</script>
</body>
</html>

In the preceding code, the template element has the aTemplate ID and is referenced using the querySelector method. The HTML markup content inside the template is then retrieved using a content property and saved in a templateContent variable. The cloneNode method is then used for deep cloning to get the activated node that is later appended to a div element. The following screenshot shows the output of the preceding code:

To find out more about the cloneNode method visit:

https://developer.mozilla.org/en-US/docs/Web/API/Node.cloneNode

Importing a node

The importNode method is another way of activating the template content. The syntax for the aforementioned method is listed in the following code:

<Node> document.importNode(<target node>,<Boolean parameter>)

The details of the preceding code syntax are listed as follows:

  • This method returns a copy of the node from an external document.
  • This method takes two input parameters. The first parameter is the target node that needs to be copied. The second parameter is a Boolean flag and represents the way the target node is cloned. If the Boolean flag is false, the importNode method makes a shallow copy, and for a true value, it makes a deep copy.

The following code shows the use of the importNode method to copy the content of a template containing an h1 element with some text:

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>
Web Component: Activating template using importNode method
</title>
</head>
<body>
<div id="container"></div>
<template id="aTemplate">
<h1>Template is activated using importNode method.</h1>
</template>
<script>
var aTemplate = document.querySelector("#aTemplate"),
container = document.getElementById("container"),
templateContent = aTemplate.content,
activeContent = document.importNode(templateContent,
true);
container.appendChild(activeContent);
</script>
</body>
</html>

In the preceding code, the template element has the aTemplate ID and is referenced using the querySelector method. The HTML markup content inside the template is then retrieved using the content property and saved in the templateContent variable. The importNode method is then used for deep cloning to get the activated node that is later appended to a div element. The following screenshot shows the output of the preceding code:

To find out more about the importNode method, visit:

http://mdn.io/importNode

HTML Import

The HTML Import is another important piece of technology of the W3C web component specification. It provides a way to include another HTML document present in a file with the current document. HTML Imports provide an alternate solution to the Iframe element, and are also great for resource bundling. The syntax of the HTML Imports is listed as follows:

<link rel="import" href="fileName.html">

The details of the preceding syntax are listed here:

  • The HTML file can be imported using the <link> tag and the rel attribute with import as the value.
  • The href string points to the external HTML file that needs to be included in the current document.

The HTML import element is implemented by the HTMLElementLink class. The IDL definition of HTML Import is listed in the following code:

partial interface LinkImport {
readonly attribute Document? import;
};
HTMLLinkElement implements LinkImport;

The preceding code shows IDL for the HTML Import where the parent interface is LinkImport which has the readonly attribute import. The HTMLLinkElement class implements the LinkImport parent interface. The browser that supports HTML Import must implement the preceding IDL.

HTML Import feature detection

The HTML Import is new to the browser and may not be supported by all browsers. To check the support of the HTML Import in the browser, we need to check for the import property that is present inside a <link> element. The code to check the HTML import support is as follows:

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>
Web Component: HTML import support
</title>
</head>
<body>
<h1 id="message"></h1>
<script>
var isImportSupported = function () {
var link = document.createElement("link");
return 'import' in link;
};
var isSupported = isImportSupported(),
message = document.getElementById("message");
if (isSupported) {
message.innerHTML = "Import is supported by the browser.";
} else {
message.innerHTML = "Import is not supported by the
browser.";
}
</script>
</body>
</html>

The preceding code has a isImportSupported function, which returns the Boolean value for HTML import support in the current browser. The function creates a <link> element and then checks the existence of an import attribute using the in operator. The following screenshot shows the output of the preceding code:

The preceding screenshot shows that the import is supported by the current browser as the isImportSupported method returns true.

The Can I Use tool can also be utilized for checking support for the HTML Import in the current browser. To check out the template support in the browser, use the following link:

http://caniuse.com/#feat=imports

The following screenshot shows the current status of support for the HTML Import in browsers using the Can I Use online tool:

Accessing the HTML Import document

The HTML Import includes the external document to the current page. We can access the external document content using the import property of the link element. In this section, we will learn how to use the import property to refer to the external document. The message.html file is an external HTML file document that needs to be imported. The content of the message.html file is as follows:

<h1>
This is from another HTML file document.
</h1>

The following code shows the HTML document where the message.html file is loaded and referenced by the import property:

<!DOCTYPE html>
<html>
<head lang="en">
<link rel="import" href="message.html">
</head>
<body>
<script>
(function(){
var externalDocument =
document.querySelector('link[rel="import"]').import;
headerElement = externalDocument.querySelector('h1')
document.body.appendChild(headerElement.cloneNode(true));
})();
</script>
</body>
</html>

The details of the preceding code are listed here:

  • In the header section, the <link> element is importing the HTML document present inside the message.html file.
  • In the body section, an inline <script> element using the document.querySelector method is referencing the link elements having the rel attribute with the import value. Once the link element is located, the content of this external document is copied using the import property to the externalDocument variable.
  • The header h1 element inside the external document is then located using a quesrySelector method and saved to the headerElement variable.
  • The header element is then deep copied using the cloneNode method and appended to the body element of the current document.

The following screenshot shows the output of the preceding code:

HTML Import events

The HTML <link> element with the import attribute supports two event handlers. These two events are listed “as follows:

  • load: This event is fired when the external HTML file is imported successfully onto the current page. A JavaScript function can be attached to the onload attribute, which can be executed on a successful load of the external HTML file.
  • error: This event is fired when the external HTML file is not loaded or found(HTTP code 404 not found). A JavaScript function can be attached to the onerror attribute, which can be executed on error of importing the external HTML file.

The following code shows the use of these two event types while importing the message.html file to the current page:

<!DOCTYPE html>
<html>
<head lang="en">
<script async>
function handleSuccess(e) {
//import load Successful
var targetLink = e.target,
externalDocument = targetLink.import;
headerElement = externalDocument.querySelector('h1'),
clonedHeaderElement = headerElement.cloneNode(true);
document.body.appendChild(clonedHeaderElement);
}
function handleError(e) {
//Error in load
alert("error in import");
}
</script>
<link rel="import" href="message.html"
onload="handleSuccess(event)"
onerror="handleError(event)">
</head>
<body>
</body>
</html>

The details of the preceding code are listed here:

  • handleSuccess: This method is attached to the onload attribute which is executed on the successful load of message.html in the current document. The handleSuccess method imports the document present inside the message.html file, then it finds the h1 element, and makes a deep copy of it . The cloned h1 element then gets appended to the body element.
  • handleError: This method is attached to the onerror attribute of the <link> element. This method will be executed if the message.html file is not found.

As the message.html file is imported successfully, the handleSuccess method gets executed and header element h1 is rendered in the browser. The following screenshot shows the output of the preceding code:

Summary

In this article, we learned about the web component specification. We also explored the building blocks of web components such as HTML Imports and templates.

Resources for Article:


Further resources on this subject:


LEAVE A REPLY

Please enter your comment!
Please enter your name here