An Introduction to Web Components

TLDR: Web components allow developers to build custom elements with rich functionality without needing to depend on heavy JavaScript frameworks.

Originally published at wearenorthern.com.

Throughout the history of the internet we’ve had various concepts of web components. jQuery plugins, Angular Directives, React, and others allowed developers to build custom components that other developers could use on their sites but they all have common drawbacks such as:

  • Having to explicitly include dependencies of the library
  • Having to add all script and style tags for the library
  • Prefixing styles so that they would not leak into the host page
  • Worrying about styles on the host page affecting the custom component

Web components are a set of standards defined by the W3C that allow developers to create custom elements while addressing the limitations mentioned above.

We’re going to introduce web components by writing two custom elements! The first element will be responsible for querying the reddit API for the top posts of a subject. It will display a title as well as create the second custom component and pass it the data from the API call.

We define a class called RedditFeedElement which will query the reddit API to get the top posts for a subject. Our element has an attribute called querythat will allow the plugin consumer to specify the topic they’re interested in displaying on their site. createdCallback is called whenever the element is created and before it is attached to the DOM.

We start by creating a shadow root with this.createShadowRoot. This is part of the Shadow DOM specification and it allows us to create a HTMLNode which is isolated from the rest of the page. This means that styles will not be inherited from the host page which may mess with our custom component. Secondly any styles we define in the shadow node will not leak into the parent page.

We create a copy of our template, clone it, and then insert it into the shadow root. Using the query attribute that was passed in we call the Reddit API and then interate over the first five results. For each result, we create a new reddit-feed-row which is another custom component and append it to our shadow root.

In order to use our element we need to register it using:

document.registerElement(‘reddit-feed’, RedditFeedElement)

Next we’ll define the component for rendering individual results.

The second component does that same setup as the first but with the addition of using the attachedCallback which is called when the custom element is added to the DOM. The data from the API is already on the dataproperty of the component and was added during its creation in reddit-feed. From there we select elements in the template and bind the data for title and image.

In order to use this element all you need to do is import the JavaScript file and use the component on the page like this:

<reddit-feed query="webdev"></reddit-feed>

To view a demo of this component, take a look at this post on our website here. (Medium doesn’t like arbitrary HTML embeds).

In our next post we plan to cover converting this component into a Polymer component and explain the benefits this brings. Feel free to ask questions, provide feedback or let us know about what you’d like to hear more of in the comments!