Ex16: Using Web Components
In this example you will learn how to write Web Components style widgets for adapters.
We will be using the LitElement library as an example. The library has different pulgins (lit-plugin, lit-html) for formating and highlighting syntaxis in the Visual Studio Code.
You can download and install them before starting the tutorial, or can find analogies in your favourite IDE.
The initial code for this exmple is stored in this branch: ex16-web-components-exercise
. You can pull it to go through the lesson.
#
Introduction to Web ComponentsWeb Components - is a way of creating reusable custom HTML-elements while encapsulating their logic and isolating CSS-styles. This method usually presumes the use of the following specifications:
Custom Elements allows the creation of custom HTML-elements with their own tag attribution. Technically, every custom element is a successor of the
HTMLElement
class that's declared in the web-page with the use of the *window.customElements.define('my-custom-element', MyCustomElement)
function. After declaration the element becomes available for reuse in DOM, the same as normal HTML-elements<my-custom-element />
.Shadow DOM provides an isolation of CSS component styles from global styles of the parent web-page. It works in two modes (
open
andclosed
), that define whether the parent web-page has access to the component's content or not. Shadow DOM doesn't use JavaScript-context, which allows it to use general link type components between the parent page and the web-component.HTML Templates are special HTML-elements under the
<template>
tag. They provide a convenient opportunity to clone the template's content into a new element, by using thetemplate.content.cloneNode(true)
function.
This approach integrates into the adapter architecture perfectly. It enables the creation of widgets by using any compatible libraries, linters, code formatting and other instruments that facilitate the development process.
#
Creating a widget#
Prerequisites- Clone the project template from this branch:
ex16-web-components-exercise
- Install
npm i
dependencies. (this example differs from others by having a librarylit
) - Run the project
npm start
- Add development servers to the extension with the following addresses:
http://localhost:3001/dapplet.json
(dapplet)http://localhost:3002/dapplet.json
(adapter)
- On a Google search result activate the dapplet
Example 16
.
#
LP: 1. Import dependenciesFirst let's import to the ./adapter/src/button.ts
the necessary elements from the library Lit
LitElement
- is a basic class which we will be inheriting from. It expands the native
HTMLElement
and hides the extra template rendering, style application, and reactive state change logic.
html
and css
- are Tagged Template Literals, which you can use to write HTML and CSS component code. The code inside literals can be highlighted and automatically formatted with the use of the according plugins, which makes the development more convenient.
property
- is a decorator. It can be used to make the properties of the component reactive and publically available to change from the outside. These properties will rerender the component when their values are altered.
Read more about other Lit possibilities in its official documentation.
#
LP: 2. Declare custom element classInherit the widget class from the LitElement
class, and implement the interface with public properties IButtonProps
.
Most likey, your IDE will not like that unrealized class properties are missing. Do not worry, we will do this below.
#
LP: 3. Declare a map between contexts and insertion pointsWidgets can work in different contexts. The contexts can have various insertion points. The compliance between them must be declared transparently.
#
LP: 4. Implement IButtonProps interfaceAdd the properties that will be available to the dapplets developer. Every property is marked with a decorator @property
, this makes them reactive.
Please be aware that there are several required properties that must be realized in your widget. They are system properties, which are defined by the Dynamic Adapter.
#
LP: 5. Add init callbackAll widgets are provided with an init
hook so that dapplets developers can do something the moment a new context appears. This moment needs to be realized transparently.
An overload of the connectedCallback()
method in LitElement allows us to subscribe to the component rendering event. We will use this.
#
LP: 6. Add a click handler functionA dapplets developer should have the possibility to subscribe to the button click event. Beforehand, we will add a click handler with a callback from the exec
property.
#
LP: 7. Write the HTML code of the widgetLet's begin writing the HTML-template of the component.
The render()
method is very similar to a method with the same name in a class-based approach to writing React.js
components. Here you can also return null
when it is not necessary to render the component. However, instead of JSX we use Tagged Template Literal - html
.
Learn more about all template possibilities in the official Lit documentation. There you can find information about using conditions in rendering, iterators, events, etc.
You can also look at an example of a complex widget from the Twitter Adapter.
#
LP: 8. Style the widget by CSSDeclaration of CSS-styles is very similar to the approach used in the styled-components
library, famous among React.js developers. Here the Tagged Template Literal - css
function is used again.
Remeber that your Web Components are rendered inside Shadow DOM, which provides an isolation of the styles. This means that global styles of the parent web-page will not be able to redefine internal styles of your component and you will not be able to use them again.
Inside Shadow DOM you can style the shadow root element with the use of a CSS pseudo-class :host()
. Sometimes this is useful for seamless website integration.
Pseudo-classes like :hover
are also available here. You can use all of CSS power to style your components.
#
Final ResultTogether we have realized a button, that will be inserted into search results on the Google search page.
The final solution is available in this branch: ex16-web-components-solution
.
The final initial code of the button is available here.