How to create Web Components by a project

Iris Carballo
Job&Talent Engineering
5 min readSep 26, 2019

--

This is a how-to about creating native web components. I will skip the style part in the explanation because it’s not so relevant and the project would still work without it, albeit in a less aesthetically pleasing way. We’ll start by explaining a little bit about what web components are, then we’ll look at an step-by-step example that can be viewed with this repo or in this live demo

What are web components?

To use web components it’s important to understand what they are, according to MDN, web components are based on three main technologies, which can be used together to create versatile custom elements with encapsulated functionality that can be reused wherever you like without fear of code collisions.

Let’s introduce some web components definitions:

Custom elements: A set of JavaScript APIs that allow you to define custom elements and their behaviour.

Shadow DOM: A set of JavaScript APIs for attaching an encapsulated “shadow” DOM tree to an element — which is rendered separately from the main document DOM — and controlling associated functionality. Elements can be scripted and styled without the fear of collision with other parts of the document.

HTML templates: The <template> and <slot> elements enable you to write markup templates that are not displayed in the rendered page. These can then be reused multiple times as the basis of a custom element’s structure.

“W3C” includes:

ES Module specification: defines the inclusion and reuse of JS documents in other JS documents.

Let’s start the project.

The idea of this project is to create a couple of components that are connected between them, not only to generate a component but also to see how you can pass data from one to another. In the end, we’ll have four buttons that, when you click on them, show you some movie quotes.

So let’s start by creating an almost empty project with index.html, style.css, and main.js files.

Our second step would be to create a container component into our main.js file to be able to pass props between its children.

https://gist.github.com/IrisCZ/0bc4a1d5328a843df9e0568b4bfb5b4b

Here we are already using the three main technologies. First of all, we are creating a class that extends HTMLElement, an API that represents an element in the HTML document tree. HTMLElement is the base type for HTMLDivElement, HTMLSpanElement, HTMLImageElement and many others and allows us to create our own HTMLElements. Custom elements allow us to extend existing (native) HTML elements as well as other custom elements.
Then we use the constructor to set some initial state, event listeners, and create the shadow DOM. An important thing here is { mode: ‘open’ }. What is this for? Well, it’s to avoid public access to the nodes within the shadow tree. So try and ‘Close the DOM!’ (this is funnier if you imagine it said by Hodor). However, both open and closed modes have the same benefits: an isolated DOM, scoped CSS, and a declarative, markup-based API. The problem is that it can be perceived as a ‘security’ feature. So maybe it is better if we keep the DOM open for now. If you’d like to find out more about it, this article is really interesting.

Last, but not least important, we are using the <slot> element from HTML templates to include, in the near future, each of our inner components.

Ok, now we already have our first web component, the hardest part… but let’s dig a little deeper. We are going to create our NavBar component.

https://gist.github.com/IrisCZ/a6907cf0cebd9e1d3be77d1c58dfcda0

There are two new things here. First, we are generating the navbar options dynamically, so we’ll have as many tabs as objects in our data file. Second, we are handling the onclick event from our new option_button. This is important because it allows us to set the selected attribute in our display component.

So finally we need to create the Display component:

https://gist.github.com/IrisCZ/4e9fdc8518bfd9cccd4d2a917911f1c5

In the Display component, we need to recover our set attribute and we will do it with static get observedAttributes(), this method should return an array of strings where each string is the name of the attribute you wish to observe. It is also aware of the changes in these attributes with the attributeChangedCallback() method. In our case, selected, this will only work with the attributes that are being observed. Finally we call the setSelected function that will return one random item inside the array in the selected object from the data file.

Conclusion

In conclusion, I would say that it is quite easy to get started with web components, especially if you have had some previous experience with frameworks such as React, Vue or any others. It would be a good launchpad to start using web components alongside the framework that you are already using as they have complementary purposes. While frameworks allow you to handle state, custom elements are stateless and provide your components with encapsulation, they also make your components agnostic which can be a important aspect of a good Design System but we will talk about this in another post.

There are also a bunch of libraries that can help you to improve your web components as much as you want:
- Stencil.js, open-source.
- Polymer, build by Google.
- And many others that you can check out here: https://www.webcomponents.org/libraries.

Hope you enjoyed this article and feel free to clone or improve my project here: https://github.com/IrisCZ/web_components_the_beginning/

Or if you just want to see it work: https://iriscz.github.io/web_components_the_beginning/

Acknowledgments: many thanks to Sergio Espeja and Bethany Solberg, this article wouldn’t be the same without them.

We are hiring!

If you want to know more about it’s like work at Jobandtalent you can read the first impressions of some of our teammates in this blog post or visit our twitter.

--

--