I got the idea for this series of articles after looking a bit deeper at the web components introduction working draft. Pretty soon I realized that the proposed component model gives us more power over our markup and introduce concepts that up to now where available only to programming languages.
This series of guides will make a brief introduction on the 4 key pieces of web components: Templates, Decorators, Custom Elements and Shadow DOM. Keep in mind that we are talking about an editors draft, and it is in no way supported by the browsers yet. I will try to explain what it is about, offer an example and explain the base functionality of each piece. Starting with Templates.
So, what are templates? Well, according to W3C, templates are
a method for declaring inert DOM subtrees in HTML and manipulating them to instantiate document fragments with identical contents.
Practically, in modern web apps we often have the need to use the same subtree of nodes multiple times, fill it with our content and append it to the tree. For example, you retrieve a list of articles from the database, and you want to append multple li tags in your document, one for each article. And of course, each li includes more nodes, like a link, an image, a paragraph etc. Until now, HTML didn’t provide a native way of doing that. So developers came up with a couple of solutions.
This was the simplest solution and the most inefficient. Just put your markup somewhere in the DOM, hide it (usually with display:none) and when needed, clone it, fill it with your data and push it back in the DOM. Of course, this had a number of disadvantages. For one, all the resources were loaded. If you had an image in there, the browser would fetch it. If you had a script, the browser would execute it. Also, the overall performance was affected for no reason. Traversal through the DOM had more nodes to go through. Selectors were slower, as well as rendering.
If I am not wrong, this was made popular by John Resig back in 2008. Practically you define your templates as strings inside a script tag. This eliminates all the disadvantages of the previous method, but it does push towards run time parsing via innerHTML which might leave you open to XSS attacks. Also, in my view it’s not semantic, since we are talking about templates and not strings.
Defining a template
Definition of a template is really easy. Just use a <template> tag and put all your code inside there. For demostration purposes we will assume about building a template for printing a list of cars.
<template id="carTemplate"> <li> <span class="carBrand"></span> <span class="carName"></span> </li> </template>
It doesn’t get any simpler than that. Keep in mind that you can have your template definition in your head or in your body, it is still valid. Like I said in the beginning, the whole subtree is inert. Meaning that it’s not actually part of the DOM. If you put there an img tag with a valid src, the browser will still not fetch the image. And if you try to select an element from the template, you will get 0 results:
document.querySelectorAll('.carBrand').length; // length is 0
If you take a look at the DOM Inspector, we can notice that the template contents are actually a DocumentFragment:
So, how do we manipulate, how do we use the template? Well the element itself has the property content, which you manipulate as if it was its own DOM. Here is an example:
var template = document.getElementById('carTemplate'); template.content.querySelector(".carBrand").length; // length is 1
And to finally make the template “go live” what we need is to clone its contents and append them to the DOM. Here is an example:
var template = document.getElementById('carTemplate'); var car = template.content.cloneNode(true); car.querySelector(".carBrand").innerHTML = "SEAT"; car.querySelector(".carName").innerHTML = "IBIZA"; document.getElementById("carList").appendChild(car);
Practically, the way of working is the same as with string templates. However, this is more standardized and we are using the tags for the job they are built for.
Here is a pen with a working example of templates, based on what has been discussed here.
Web components are still an editors draft. The spec will probably go through a lot of changes in the future. Also keep in mind that browser support is very poor at the moment. Latest version of Chrome seems to support a good subset of the features defined, but the biggest support comes with Chrome Canary.