In this series we explore the Web Component APIs: HTML Imports, Custom elements, HTML Templates, and the Shadow DOM, seeing how each of these APIs can be used within the context of your Aurelia applications. In this installment, we’ll look at the features Aurelia provides around HTML templates and custom elements.
This template would then be rendered by implementing a Backbone view, which looked the template up by ID using jQuery, and rendered it using the Underscore.js templating engine. This method (termed Overloading script) was pioneered by John Resig in his Micro Templating Utility back in 2008. This approach is actually great for the most part. Because as the
script tag is set to
.innerHTML using the rendered template combined with this input it can lead to XSS vulnerabilities. So long as you’re aware of these vulnerabilities it’s not a problem, but ideally, there would be a standard approach that circumvents it all together. You can find out more about the pros and cons of this template method on the HTML 5 Rocks – Template Tutorial.
<info-card> HTML snippet. An important thing to note here is that image in the snippet isn’t rendered when the page is loaded. Instead, we need to explicitly create an element for it and load it into the DOM. Using templates is as simple as declaring a new
<template> element with some content:
After declaring the template element, we need to query it from the DOM
document.querySelector('#info-card'), clone the node, creating a new copy of the DOM fragment from the template so that it can be included in the current document
document.importNode(infoCard.content, true), and then append cloned node to the current document
Using HTML Templates with Aurelia
Aurelia views are created using HTML templates. When the Aurelia framework loads it parses the template and creates a view instance which it then initializes with data-binding and so on. You can find out more about the Aurelia view initialization process in this great post by Jeremy Danyow on the Aurelia Hub. Aurelia adds templating features such as repeaters, one-way and two-way data-binding, binding behaviors, input validation and so on primarily through the use of custom HTML attributes. This keeps the view syntax as close to standard HTML as possible. The equivalent info card view template in Aurelia might look something like this:
The striking thing about the template syntax in the above example is how close it is to the vanilla web component template we saw earlier.
I was first introduced to the idea of custom elements with Angular 1 directives, which provided a way of declaring an HTML snippet (view) and linking it to a backing controller. Since then just about every SPA framework has implemented custom elements in some way shape or form. Custom elements extend the
HTMLElement class and should be prefixed with an X. To refer back to the
info-card template from earlier, if we wanted to implement this as a vanilla custom element we’d first need to create an
XInfoCard class which derived from
HTMLElement. It’s also possible to attributes on a custom element using the
observedAttributes() method, and respond to changes by implementing the
attributeChangedCallback in the custom attribute class:
You could then use the custom element as follows:
For various reasons (primarily performance), the Aurelia team chose to create a framework specific implementation of custom elements, rather than using the vanilla web components option. These custom elements are the bedrock of Aurelia’s component system. You create them by first implementing a view-model (for example
info-card.js), which is analogous to the
XInfoCard class in the vanilla web components example, and then creating the corresponding HTML view template. Instead of needing to implement custom callbacks to watch for attributes changing, Aurelia handles this by convention, as you’ll see in the below example:
info-card.js – the view-model
You then need to create the corresponding view file (which as we saw earlier is just a standard HTML template):
info-card.html – the view
You can use the custom element as follows:
This passes the message from a parent component down to the
info-card component using one-way data-binding.
Whilst Aurelia doesn’t leverage vanilla custom elements under the hood, I think the trade-off is worth it. This design choice allows for the performance gains and an elegant development model.
This concludes the overview of how you can use Templates and Custom Elements in Aurelia. In the next post, we’ll the Shadow DOM, arguably the most important, and my favorite feature of web component API.