日本語版はこちら

In this codelab, you'll learn how to build elements using LitElement. You'll create a simple LitElement element, a toggle button. The finished button will look something like this:

You'll be able to use it with simple markup like this:

<icon-toggle></icon-toggle>

This project introduces you to most of the key concepts in working with LitElement.

Don't worry if you don't understand everything. Each of the concepts presented here is described in detail in the LitElement documentation.

To start the tutorial, you will need some software:

You'll also need to have some basic skills and knowledge:

Install Git

Git is a version control tool.

Download the Git Installer

  1. Run the Git installer.
  2. Check whether Git is correctly installed: git --version

If all is well, Git tells you its version info:

If you don't see a Git version number git version 2.19.1 at this point, you may need to refer to the official Git installation instructions.

Install Node and npm

Node is a JavaScript runtime environment. npm is a package manager for Node. They will both be installed when you install Node.

Download the Node installer

  1. Download and run the Node installer (this will install npm as well).
  2. Update npm to the latest version: npm install npm@latest -g
  3. Check that Node and npm are correctly installed. Run the following commands:

node -v is v10.14.2 at this point

npm -v is 6.4.1 at this point

If you don't see version numbers for Node and npm, you may need to refer to the official installation instructions on the npm website.

Install the Codelab

Clone this repo:

git clone https://github.com/Polymer-Japan/litelement-first-element.git

Install Dependencies

Change directory to your local repo and install dependencies with npm

cd litelement-first-elements
npm install

Fetching the components may take some time if your internet connection is slow.

When the installation finishes, your project folder should look something like this:

The main file you'll work with is icon-toggle.js, which contains the definition for your custom element.

Run the demo

Cool - you made an app! It's that easy. The app doesn't do much yet, but let's take a look at it.

npm start

The Polymer development server starts up, and opens the demo in a new browser tab. You'll see some text where the icon toggles should appear. It doesn't look very interesting, but it shows everything is working.

Next, you'll create a simple element that displays an icon.

In this step, you'll learn about:

Edit icon-toggle.js

Open icon-toggle.js in the root on the your Editor. This file contains the skeleton of a custom element.

Start by taking a look at the existing code:

Starting code—ES6 Module imports

import { LitElement, html } from 'lit-element';
import '@polymer/iron-icons/iron-icons.js';
import '@polymer/iron-icon/iron-icon.js';
        

Key information:

Next is the definition of the element itself:

Starting code—Shadow DOM template



class IconToggle extends LitElement {
  render() {
    return html`
      <style>
        /* local DOM styles go here */
        :host {
          display: inline-block;
        }
      </style>
      <!-- local DOM goes here -->
      <span>Not much here yet.</span>
    `;
  }
}

        

Key information:

Starting code—element registration


window.customElements.define('icon-toggle', IconToggle);
        

Key information:

Create the shadow DOM structure

Now that you're familiar with the basic layout of the element, add something useful to its shadow DOM template.

Find the <span> below the local DOM goes here comment:

icon-toggle.js—before

    <!-- local DOM goes here -->
    <span>Not much here yet.</span>
  `;

Replace the <span> and its contents with the <iron-icon> tag below:

icon-toggle.js—after

    <!-- local DOM goes here -->
    <iron-icon icon="polymer">
    </iron-icon>
  `;

Key information:

Style the shadow DOM

There are a number of new CSS selectors to work with shadow DOM. The icon-toggle.js file already includes a :host selector, discussed earlier, to style the top-level <icon-toggle> element.

To style the <iron-icon> element, add the following CSS inside the <style> tag after the existing content:

icon-toggle.js

    <style>
      /* local styles go here */
      :host {
        display: inline-block;
      }
      iron-icon {
        fill: rgba(0,0,0,0);
        stroke: currentcolor;
      }
      :host([pressed]) iron-icon {
        fill: currentcolor;
      }
    </style>

Key information:

Your custom element definition should now look like this:

icon-toggle.js


import { LitElement, html } from 'lit-element';
import '@polymer/iron-icons/iron-icons.js';
import '@polymer/iron-icon/iron-icon.js';

/**
 * `icon-toggle`
 * Get started creating custom elements with LitElement
 *
 * @customElement
 * @demo demo/index.html
 */
class IconToggle extends LitElement {
  render() {
    return html`
      <style>
        /* local styles go here */
        :host {
          display: inline-block;
        }
        iron-icon {
          fill: rgba(0,0,0,0);
          stroke: currentcolor;
        }
        :host([pressed]) iron-icon {
          fill: currentcolor;
        }
      </style>
      <!-- local DOM goes here -->
      <iron-icon icon="polymer">
      </iron-icon>
    `;
  }
}

window.customElements.define('icon-toggle', IconToggle);

Setting initial value on Demo page

To display message according to the value in the host element. Please add constructor method for setting the initial value to isFav property.

icon-toggle-demo.js

class IconToggleDemo extends LitElement {
  constructor() {
    super();
    this.isFav = false;
  }
        

Reload the demo. You should see the toggle buttons show up with the hard-coded icon.

You'll notice that one toggle is styled as pressed, because the pressed attribute is set in the demo. But click all you want, the button won't toggle yet; there's no code to change the pressed property.

Right now, the element doesn't do much. In this step, you'll give it a basic API, allowing you to configure the icon from markup, using an attribute, or from JavaScript, using a property.

First, a bit of data binding. Find the <iron-icon> element and change the value of the icon attribute from "polymer" to "${this.icon}".

icon-toggle.js

<!-- local DOM goes here -->
<iron-icon icon="${this.icon}">
</iron-icon>

Key information:

You could now use your element and set the toggleIcon property in markup or using JavaScript, as shown in the following examples. (You don't need to add this code to your project.)

Example—setting the icon using markup

<icon-toggle icon="favorite"></icon-toggle>

Example—setting the icon from JavaScript

var myToggle = document.querySelector('icon-toggle');
myToggle.icon = "favorite";

Next, add a declaration for the icon property.

Add the following static get properties function to the IconToggle class:

icon-toggle.js

class IconToggle extends LitElement {
  static get properties() {
    return {
      icon: String,
    };
  }

Key information:

The properties object also supports several more features. Add the following lines to add support for the pressed property:

icon-toggle.js


  constructor() {
    super();
    this.pressed = false;
  }
  static get properties() {
    return {
      icon: String,
      pressed: {
        type: Boolean,
        reflect: true
      }
    };
  }

Key information:

Now your element has pressed and icon properties working.

Reload the demo, and you should see star and heart icons instead of the hard-coded icon from the previous step:

If you're curious about where the stars and hearts come from, you can take a peek at demo/icon-toggle-demo.js and see lines like this:

<icon-toggle toggle-icon="star"></icon-toggle>
<icon-toggle toggle-icon="star" pressed></icon-toggle>

Of course, a button isn't a button if you can't click it. To toggle the button, add an event listener. To add event listeners on the iron-icon element, add the @click attribute to the element:

icon-toggle.js

<iron-icon icon="${this.icon}" @click="${this.toggle}">

Key information:

Add a handler called by the event listener.

icon-toggle.js

  toggle() {
    this.pressed = !this.pressed;
  }
  attributeChangedCallback(name, oldval, newval) {
    super.attributeChangedCallback(name, oldval, newval);
    if(name === 'pressed') this.dispatchEvent(new CustomEvent('pressed-changed', { detail: this.pressed }));
  }
        

Key information:

Save the icon-toggle.js file and reload the demo again. You should be able to press the button and see it toggle between its pressed and unpressed states.

You now have a button that's basically functional. But it's stuck using the existing text color for both pressed and unpressed states. What if you want to get a little flashier?

Shadow DOM helps prevent users from styling your element's internals by accident. Using custom properties, your element can expose a specific set of user-styleable properties.

You apply a custom property inside your element using the `var` function.

background-color: var(--my-custom-property, defaultValue);

Where --my-custom-property is a custom property name, always starting with two dashes (--), and defaultValue is an (optional) CSS value that's used if the custom property isn't set.

Edit your element's <style> tag and replace the existing fill and stroke values with custom properties:

icon-toggle.js

  <style>
    /* local styles go here */
    :host {
      display: inline-block;
    }
    iron-icon {
      fill: var(--icon-toggle-color, rgba(0,0,0,0));
      stroke: var(--icon-toggle-outline-color, currentcolor);
    }
    :host([pressed]) iron-icon {
      fill: var(--icon-toggle-pressed-color, currentcolor);
    }
  </style>

Because of the default values, you can still style the <icon-toggle> just by setting color, but now you have other options. Open up demo/icon-toggle-demo.js and set the new properties:

icon-toggle-demo.js

    <style>
      :host {
        font-family: sans-serif;
        --icon-toggle-color: lightgrey;
        --icon-toggle-outline-color: black;
        --icon-toggle-pressed-color: red;
      };
    </style>

Reload the demo again to get colorful.

That's it — you're finished. You've created an element that has a basic UI, API, and custom styling properties.

If you have any trouble getting the element working, check out the finished version.