Skip to content

gramener/lit-html-workshop

Repository files navigation

lit-html Workshop

This workshop is for JavaScript developers on lit-html - a standalone HTML/SVG rendering library. We like it because:

  1. It's like g1 templates or lodash templates, but re-renders only changed elements (i.e. faster and transitionable)
  2. It's lighter than Vue, React, or Angular, and requires no compilation (like Svelte)
  3. It's purely HTML/JS standard-based, and is supported by Google

Render a basic template

STEP 1: Log into Codepen and Create a new pen titled lit-html workshop

STEP 2: Add this HTML:

<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
<div class="container">
  <h1 id="title"></h1>
  <div id="report" class="table-responsive"></div>
</div>

STEP 3: Add this JS:

import {html, render} from 'https://unpkg.com/lit-html?module';

render(html`Marvel Superpowers`, document.querySelector("#title"));

A H1 titled "Marvel Superpowers"

Render a table

STEP 1: Add this code to the JS to fetch Marvel Superpowers data.

const url = "https://raw.githubusercontent.com/sanand0/marvel-powers/master/marvel-powers-summary.json";
const data = await fetch(url).then(r => r.json())

STEP 2: Add this code to the JS to render 1 row per Marvel character:

const table = () => html`
  <table class="table bordered">
    ${data.map(row => html`
      <tr>
        <td><a href="${row.url}">${row.name}</a></td>
      </tr>
    `)}
  </table>
`
render(table(), document.querySelector("#report"));

You should see a table like this:

Table with 1 row per character

STEP 3: Replace the const table = ... with the code below. It appends 1 column for each power.

const powers = ["Durability", "Energy_Projection", "Fighting_Skills", "Intelligence", "Speed", "Strength"];
const table = () => html`
  <table class="table table-bordered">
    <thead>
      <tr><th>Character</th>${powers.map(power => html`<th>${power}</th>`)}</tr>
    </thead>
    <tbody>
      ${data.map(row => html`
        <tr>
          <td><a href="${row.url}">${row.name}</a></td>
          ${powers.map(power => html`
            <td>
              <span class="min">${row[`min ${power}`]}</span> -
              <span class="max">${row[`max ${power}`]}</span>
            </td>
          `)}
        </tr>
      `)}
    </tbody>
  </table>
`

The table should look like this:

Table with characters and power ranges

Dynamic content

STEP 1: Add this slider below <h1> in the HTML:

  <input class="form-range" type="range" id="power" min="0" max="14" value="0">

STEP 2: Change the table function to accept a power parameter:

const table = (power = 0) => html`
  ...

and replace data.map(... with:

      ${data.filter(v => powers.every(p => v[`min ${p}`] + v[`max ${p}`] >= power)).map(row => html`

STEP 3: Add this code to the JS to render the table based on the slider value:

document.querySelector("#power").addEventListener("input", () => {
  const power = document.querySelector("#power").value;
  render(table(power), document.querySelector("#report"));
});

Test it

Move the slider. The table should automatically be filtered by the power.

Output

Bonus

Color the table cells based on the min + max powers (e.g. green for 14 and red for 2).

Submit your code

  1. Create an issue titled Exercise submission. Add a link to your CodePen and submit the issue.

Verification

To mark a submission as correct:

  1. Check if the slider filters for the characters with the most power.
  2. Check if the code renders the table using lit-html.

Video

Workshop video

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published