On February the 5th Google announced LitHTML was, finally, at version 1 and LitElement had reached version 2. To celebrate I'm going to have a look at web components and, using the guide, convert my material design switches into elements.
The aim is to be able to just write some simple HTML and get a simple, nice and accessible toggle switch back. I'll be using JSFiddle to show the various steps.
<md-switch>Toggle switch</md-switch>
Create
This part has 3 steps that we'll need to work through in order to register our element. We do these steps in Javascript.
- Import the LitElement base class and html helper function.
- Create a class for your element that extends the LitElement base class.
- Register the new element with the browser.
With importing the project I don't have it locally but know that I can see it hosted here https://unpkg.com/lit-element/lit-element.js?module
which is why my import line says to get LitElement
and html
from there.
The most important, and hardest, part of any project is naming. When making a web component the name must contain a hyphen, like foo-bar
, following general convention we should name our class the same as our element but with hyphens removed and each new word having a capital letter, like FooBar
. Our project is called md-switch
.
The render function defines your componentโs template. You must implement render for every LitElement component.
Our render is a simple paragraph containing "Hello world!".
Finally, we need to register the element. This is where we let the browser know md-switch
elements are associated with the MdSwitch class.
Customising
Now let's get the HTML for our switches. If you want to read about the logic behind the markup and the styles I suggest you read my older post linked above.
<label class="md_switch">
<input type="checkbox" />
<span class="md_switch__toggle"></span>
Toggle switch
</label>
You'll notice the label text for the switch is static. This is where slots
come in handy. They allow you to take the data/text between that tags in the html and 'slot' it into your template.
Properties
Now we'll look at properties. In reality, our switch is a stylised checkbox so needs all of the same properties/attributes. I'm only going to include checked and disabled for this example as they're the most important and will give you a good enough idea of how to implement more.
To add a property we need to add an object to contain them. The litElement way of doing this is with a static get called Properties.
Our object should contain checked
and disabled
these are both Boolean
values and are both attributes of our element.
{checked: { type: Boolean, attribute: true }}
This is good but now we need to pass these properties to our template. Because our properties are boolean we can use the ?
operator, which looks like this:
?checked="${this.checked}"
Events
We don't have to do much with events on this project but we do want to keep our input's checked state and our elements checked state in sync. The easiest way to achieve this is to have an onchange
event that updates md-switch
's checked state when the input's changes.
The way we do this is with the @
operator. In our template we say @eventname="{this.functionName}"
we want the change event so we'll use @change
we'll also need a new function.
Style
To add our styles we need to add css
to our initial import. Then we need a static get called styles that returns some CSS and that's it.
Fin
And that's all there is to it. Web components make reusing elements super easy but you don't have to make all your elements your self. There is a site called https://www.webcomponents.org/ which has thousands of elements you can use in your projects, some elements are better than others so be careful.
I hope this made sense to you and would love to see any elements you have made yourselves. Thanks for reading!
๐ฆ๐ง ๐๐ฆ๐ฆ๐โค๐ง ๐โค
Top comments (4)
Awesome post. Way to go!
If you're using Rollup to bundle your app, you can import styles from CSS with this plugin:
npm.im/rollup-plugin-lit-css
Which is precisely equivalent to :
I hope this tides us over until the css modules proposal is implemented across browsers
It weirdly reminds me of VueJS: the
html
part looks a lot like the<template>
(the@
syntax for events and<slots>
), thecss
part reminds me of the VueJS<style>
section and theclass
is the<script>
section.Cool :-)
This is great! One question, how would you pass in multiple parameters? Would it look something like this?
I don't think you'd ever want to add more parameters with an event. Looking at your example the params were attached to
this
anyway so we can just get them with the function.