mcpField
J
json-to-html-table-with-lit

json-to-html-table-with-lit

github.com/rodydavis開発6047 回インストール2 週間前に更新
リポジトリ

json-to-html-table-with-lit について

Litを使うWeb開発者向けのチュートリアルです。URLまたはインラインのJSONからHTMLテーブルを生成し、セル編集、イベント通知、ヘッダーのカスタマイズを追加する方法を紹介します。

主な機能

  1. 01URLまたはインラインJSONから表を生成
  2. 02テーブルセルの編集
  3. 03イベントによるセルデータの取得
  4. 04JSONキーに応じたヘッダーセルの置換
  5. 05CSSカスタムプロパティによるスタイル設定

活用シーン

  1. 01WebページでのJSONデータ表示
  2. 02JSONテーブルへのセル編集機能の追加

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/rodydavis/skills --skill json-to-html-table-with-lit

インストール後、Claude Code で/json-to-html-table-with-litを入力して読み込まれたか確認します。

詳細

Lit を使用した JSON から HTML テーブルへの変換

この記事では、Lit の Web コンポーネントをセットアップし、それを使用して JSON の URL またはインライン JSON から HTML の テーブルを作成する方法を説明します。

TLDR 最終的なソースコードはこちら、オンラインのデモはこちらです。

前提条件

  • Vscode
  • Node >= 16
  • Typescript

はじめに

まず、ターミナルでプロジェクトの場所に移動し、次のコマンドを実行します。

npm init @vitejs/app --template lit-ts

次に、プロジェクト名として lit-html-table を入力します。プロジェクトを vscode で開き、依存関係をインストールします。

cd lit-html-table
npm i lit
npm i -D @types/node
code .

vite.config.ts を次のように更新します。

import { defineConfig } from "vite";
import { resolve } from "path";

export default defineConfig({
  base: "/lit-html-table/",
  build: {
    lib: {
      entry: "src/lit-html-table.ts",
      formats: ["es"],
    },
    rollupOptions: {
      input: {
        main: resolve(__dirname, "index.html"),
      },
    },
  },
});

テンプレート

index.html を開き、次のように更新します。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/src/favicon.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>JSON to Lit HTML Table</title>
    <script type="module" src="/src/lit-html-table.ts"></script>
  </head>

  <body>
    <lit-html-table src="https://jsonplaceholder.typicode.com/posts">
      
      
    </lit-html-table>
  </body>
</html>

この例では Web コンポーネントに src 属性を渡していますが、application/json を type 属性に設定した script タグを追加し、その内容に JSON を記述することもできます。

テーブルのヘッダーセルを置き換える必要がある場合は、JSON オブジェクトのキーを slot 名に設定した要素を指定できます。

Web コンポーネント

コンポーネントを更新する前に、my-element.ts の名前を lit-html-table.ts に変更します。

lit-html-table.ts を開き、次のように更新します。

import { html, css, LitElement } from "lit";
import { customElement, property } from "lit/decorators.js";

type ObjectData = { [key: string]: any };

@customElement("lit-html-table")
export class LitHtmlTable extends LitElement {
  @property() src = "";

  data?: ObjectData[];

  static styles = css`
    tr {
      text-align: var(--table-tr-text-align, left);
      vertical-align: var(--table-tr-vertical-align, top);
      padding: var(--table-tr-padding, 10px);
    }
  `;

  render() {
    // Check if data is loaded
    if (!this.values) {
      return html`<slot name="loading">Loading...</slot>`;
    }
    // Check if items are not empty
    if (this.values.length === 0) {
      return html`<slot name="empty">No Items Found!</slot>`;
    }
    // Convert JSON to HTML Table
    return html`
      <table>
        <thead>
          <tr>
            ${Object.keys(this.values[0]).map((key) => {
              const name = key.replace(/\b([a-z])/g, (_, val) =>
                val.toUpperCase()
              );
              return html`<th>
                <slot name="${key}">${name}</slot>
              </th>`;
            })}
          </tr>
        </thead>
        <tbody>
          ${this.values.map((item) => {
            return html`
              <tr>
                ${Object.values(item).map((row) => {
                  return html`<td>${row}</td>`;
                })}
              </tr>
            `;
          })}
        </tbody>
      </table>
    `;
  }

  async firstUpdated() {
    await this.fetchData();
  }

  // Download the latest json and update it locally
  async fetchData() {
    let _data: any;
    if (this.src.length > 0) {
      // If a src attribute is set prefer it over any slots
      _data = await fetch(this.src).then((res) => res.json());
    } else {
      // If no src attribute is set then grab the inline json in the slot
      const elem = this.parentElement?.querySelector(
        'script[type="application/json"]'
      ) as HTMLScriptElement;
      if (elem) _data = JSON.parse(elem.innerHTML);
    }
    this.values = this.transform(_data ?? []);
    this.requestUpdate();
  }

  transform(data: any) {
    return data;
  }
}

テーブルセルのスタイル設定用にいくつかの CSS カスタムプロパティ を定義しましたが、ここにはさらに多くのプロパティを追加できます。

すべてがうまくいったら、npm run dev コマンドを実行します。次のように表示されます。

README の画像

編集

すべてのセルの編集に対応するにはどうすればよいでしょうか。Lit と Web コンポーネントを使えば、HTML を変更せずに段階的に機能を拡張できます。

クラスの先頭に、次のブール型プロパティを追加します。

@property({ type: Boolean }) editable = false;

次に、render メソッドの tbody タグを更新します。

<tbody>
  ${this.values.map((item, index) => {
    return html`
      <tr>
        ${Object.entries(item).map((row) => {
          return html`<td>
            ${this.editable
              ? html`<input
                  value="${row[1]}"
                  type="text"
                  @input=${(e: any) => {
                    const value = e.target.value;
                    const key = row[0];
                    const current = this.values![index];
                    current[key] = value;
                    this.values![index] = current;
                    this.requestUpdate();
                    this.dispatchEvent(
                      new CustomEvent("input-cell", {
                        detail: {
                          index: index,
                          data: current,
                        },
                      })
                    );
                  }}
                />`
              : html`${row[1]}`}
          </td>`;
        })}
      </tr>
    `;
  })}
</tbody>

editable が true かどうかを確認し、true の場合は、データを更新して input イベントをディスパッチするイベントリスナーを備えた入力欄を返します。

index.html に editable 属性を追加します。

<lit-html-table editable> ... </lit-html-table>

再読み込みすると、テーブルは次のように表示され、どのセルも編集できるようになります。

README の画像

最新の値やセルの情報を取得するには、index.html の閉じる body タグの直前にイベントリスナーを追加します。

<script>
  const elem = document.querySelector("lit-html-table");
  elem.addEventListener(
    "input-cell",
    (e) => {
      // Index and data for the individual cell
      const { index, data } = e.detail;
      // New array of json items
      const values = elem.values;
    },
    false
  );
</script>

値の型を確認して、色、数値、またはチェックボックスの入力欄を返すことで、さらに機能を拡張できます。

まとめ

Lit を使った開発について詳しく知りたい場合は、ドキュメントをこちらでご覧いただけます。Lit playground にもこちらに例があります。 この例のソースはこちらで確認できます。

コメント