Building a Pager Web Component – Part 2: Template & Shadow DOM

In the last post, we started building a pager web component. In this post, we will continue with this, making use of a template and the shadow DOM.

Moving the markup to a template

At the moment, the markup for our component is defined in createdCallback(). Let’s now define this in a template with some styling:

We now need to reference this template in createdCallback() – we do this using:

Adding the markup to the shadow DOM

In order to use the markup that we have extracted from the template, we will use the shadow DOM. First we need to get a reference to the shadow root using this.createShadowRoot(). Then we add the template’s content to the shadow root using root.appendChild().

The full listing for our component is now:

Our component now looks like below.

pager component

Next time we’ll separate our component into it’s own html file.

Building a Pager Web Component – Part 1: Basic Custom Element

Following on from my last post, Getting into Web Components, I’m going to do a series of posts that cover building a pager web component. The component will have links to navigate through pages and text to display what page we are on. Hopefully, we will end up with something like this:

pager component

Referencing the component

Before we build our component, let’s reference it on the page. First we need to think of a name for our component. The name must contain a hypen – let’s go for “x-pager”. Let’s also have attributes for the current page and total number of pages. So, our referencing markup could be:

Defining the custom element

In order to define the custom element, we need to register it by using document.registerElement(elementName, options). In our case the call is:

where Proto is the prototype for the component which we can create using Object.create(HTMLElement.prototype). The final thing we will do in this post is to generate some markup in the component which is achieved using createdCallback() on the component’s prototype. The full listing for our component at this stage is:

At this stage our component looks like below. We’ll tidy this up a bit in the next post.

pager component

Getting into Web Components

Why?

Here are the main benefits of web components …

More readable markup

Let’s have a look at a bootstrap dropdown component from their examples page. There’s a fair bit of noise here for a simple example.

Wouldn’t it be much cleaner and easier to read if the markup was as follows:

How about some of the markup from Gmail – how readable is this?

Gmail

Standard way

For many years we have had the ability to create reusable web UI components. Server side technologies like ASP.NET gave us the ability to create server driven reusable controls. In more recent years, the flexibility of HTML, CSS and JavaScript has been leveraged to give us components like jQueryUI and Boostrap. However, the approaches and the consumption of these controls has differed from control vendor to control vendor. This means we waste time as developers in getting up to speed when using 3rd party web components. Web components gives us a standard approach which will hopefully mean the ramp up time when using 3rd party web components will be quicker.

So what are they?

Web components is an unbrella term for 4 new browser technologies …

Custom elements

Custom elements gives us the ability to create reusable and meaningful HTML elements like <bs-dropdown> in the above example. They can extend existing HTML elements, so, you could create <x-superbutton> that extends <button>.

Templates

Templates allows you to define HTML templates on the client. But why do we need this when libraries like Handlebars.js already lets us do this?

handlebars

The key advantage that native templates bring is that inside the template, nothing runs or renders. Obviously this helps performance but it also protects the template from XSS risks.

Shadow DOM

Shadow DOM allows you to scope a web component. The reasons for scoping are to protect consumers of the component from accidentally styling bits of the component or stop the component accidentally styling other parts of the page. Native HTML controls such as <video> already use shadow DOM as you can see from the following markup.

video tag

Imports

Imports allows you to bundle the HTML, CSS and JavaScript for a web component into a single reusable package. So, in a web page, instead of referencing the HTML, CSS and JavaScript separately …

… we can reference just a single HTML file …

Can I use them today?

Are We Componentized Yet? gives great information on this. As we stand today, the good news is that we can use them in Chrome. However, it appears that IE and Safari still have a lot of work to do. You also need to bare in mind that all 4 specifications are still in working draft, so, things could change.

There are a number of libraries that we can use today that are alternatives to native web components. Two of the most popular ones are polymer and X-Tag. Both these libraries support all the modern browsers but only go back to IE10.

Productivity Tips in Chrome DevTools

Here are a few things that have helped my dev workflow in the last few years in Chrome DevTools …

UI Inspection

When debugging UI, I have found Inspect element a great way to drill straight into complicated UIs.

Inspect element

Right click where you want to drill in on the page, and choose Inspect element and the relevant node in the mark up will be highlighted.

UI fiddling

When creating new UI, I find it really useful to fiddle with the UI in the elements panel. I drill into the UI element using Inspect element and add attributes to element.style in the style section. This is great for fiddling with font sizing, margins and colours.

UI Fiddle

Navigating JavaScript

When navigating through JavaScript code, I find remembering a couple of shortcut keys speeds this process up for me.

Ctrl P allows you to navigate through different files. After typing Ctrl P, a list of files will appear. Start typing the name of the file you want to open and the list will reduce. Use the down arrow key to move to the required file in the list and hit the return key to open the file.

Shift Ctrl P will allow you to navigate through functions within a file. Again after typing Shift Ctrl P, a list of functions will appear. Start typing the name of the function you want to go to and the list will reduce. Use the down arrow key to move to the required function in the list and hit the return key to go to the function.

JS navigation

Stepping through JavaScript

When debugging your JavaScript, F11 will step through the lines of code. I find it really useful to be able to step over certain functions like calls to 3rd party libraries – F10 allows you to do that.

Conditional Breakpoints

You add a breakpoint in your JavaScript by clicking on the left margin on the line number. When debugging code that gets called many times (e.g. code in a loop), I find that I can get to the point I want to debug quicker by turning the breakpoint into a conditional breakpoint. To do this, right click on the breakpoint and select Edit breakpoint …. You then need to specify a JavaScript expression that evaluates to true when you want your breakpoint to activate.

JS breakpoints

Make it bigger

I find it hard to read the JavaScript, HTML, … in DevTools – it’s too small (I must be getting old!). Ctrl + will make all the text in DevTools bigger.

Edit your source

Whilst debugging HTML, JavaScript and CSS in DevTools, being able to make changes and continue debugging without having to go back to my code editor, speeds up my workflow. Before you can do this, you will need to associate your web app’s folder with a workspace in DevTools. To do this, right click in the left panel of the sources panel and select Add folder to workspace.

add workspace

Before you can make and save changes to files in DevTools, you need to carry out one more step … In the sources panel, right click on the file you want to change and select Map to file system resource… and then select the folder in the list that appears. Luckily, DevTools remembers the workspace and file mappings when you next open your web app in DevTools.

Map to file 1
Map to file 2

You can then make the changes to your code directly in the source panel and hit Ctrl S to save the changes in the actual source file.

Use the console to inspect and test

Using the console to inspect the state of variables has helped me a lot in my debugging process. Just type a variable and you get details of the whole object graph for that variable. You can even change the state of the variables in here as well during your debugging process.

Console