機能拡張v.1

前章までは、見た目だけで機能はない。 本章では、簡単な検索機能を実装する。そこから、各フラグメントの連携手段を話す。

サンプルコードは、こちら

組成

team-composite/index.html

<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
  <title>team-composite</title>
</head>
<style>
  #id {
    margin: 5%;
  }
  .wrapper {
    display: grid;
  }
  team-search-box {
    border: medium dotted red;
  }
  team-product-list {
    border: medium dotted blue;
  }
  team-inspire-list {
    border: medium dotted green;
    grid-column-start: 2;
    grid-column-end: 2;
    grid-row-start: 1;
    grid-row-end: 3;
  }
</style>
<body>
  <div id="root"></div>
  <script type="module">
    import { html, render } from 'lit-html';
    import './inspire/team-inspire.js';
    import './search/team-search.js';
    import './product/team-product.js';
    import { EventBus } from './src/eventBus.js';
    render(
      html`
        <div class="wrapper">
          <team-search-box></team-search-box>
          <team-product-list></team-product-list>
          <team-inspire-list>
            <team-inspire-label></team-inspire-label>
          </team-inspire-list>
        </div>
      `,
      document.querySelector('#root')
    );
    new EventBus().launch();
  </script>
</body>
</html>

new EventBus().launch();が、各フラグメントのイベントを伝搬するクラスとします。

team-composite/src/eventBus.js

export class EventBus {
   launch() {
        document
        .querySelector('team-search-box')
        .addEventListener('submit', (e) => {
          document
          .querySelector('team-product-list')
          .dispatchEvent(new CustomEvent('update', e))
          document
          .querySelector('team-inspire-list')
          .dispatchEvent(new CustomEvent('update', e))
        });
    }
}

team-search-boxsubmit(カスタム)イベントをteam-product-listteam-inspire-listへ伝搬します。

フラグメント

team-search/team-search.js

import { TeamSearchBox } from './src/TeamSearchBox.js';

window.customElements.define('team-search-box', TeamSearchBox);

team-search-text/src/TeamSearchBox.js

import { html, css, LitElement } from 'lit-element';

const items = ['apple', 'banana', 'grapes', 'mango', 'orange'];
export class TeamSearchBox extends LitElement {
  static get styles() {
    return css`
      button {
        background-color: inherit;
      }
      input {
        width: 50%;
      }
    `;
  }
  static get properties () {
    return {
      inputValue: {
        type: String
      }
    }
  }
  constructor () {
    super();
    this.inputValue = "";
  }
  updateInputValue (e) {
    this.inputValue = e.srcElement.value
  }
  submit() {
    const filterItems = (arr, query) => {
      return arr.filter(el => el.toLowerCase().indexOf(query.toLowerCase()) !== -1)
    }
    this.dispatchEvent(new CustomEvent("submit", {
      detail: {
        items: filterItems(items, this.inputValue) 
      }
    }));
  }
  render() {
    return html`
    <input placeholder="Please enter keywords ..." value="${this.inputValue}" @change=${this.updateInputValue}></input>
    <button @click=${()=>this.submit()}>🔍</button>
    `;
  }
}

検索ボタンをクリックしたらdispatchEvent(new CustomEvent("submit",{...})を発火。

team-product-list

team-product-listは、次のjsから読み込む。

team-product/src/team-product.js

import {TeamProductItem} from './src/TeamProductItem';
import {TeamProductList} from './src/TeamProductList';

window.customElements.define('team-product-item', TeamProductItem);
window.customElements.define('team-product-list', TeamProductList);

team-product/src/TeamProductList.js

import { html, css, LitElement } from 'lit-element';

const items = ['apple', 'banana', 'grapes', 'mango', 'orange'];
export class TeamProductList extends LitElement {
  static get styles() {
    return css`
      team-product-item {
        margin: 10px 0;
        display: block;
        width: 90%;
      }
    `;
  }

  static get properties() {
    return {
      items: { type: Array },
    };
  }

  constructor() {
    super();
    this.items = items;
    this.addEventListener('update', this._handleUpdate);
  }

  _handleUpdate(e) {
    this.items = e.detail.items;
  }

  render() {
    return html`
      ${this.items.map(item => {
        return html`<team-product-item .name=${item}></team-product-item>`;
      })}
    `;
  }
}

このカスタム要素は、this.addEventListener('update', this._handleUpdate);updateイベントによって更新される。

結果

その結果、次のような画面が表示される。

04_function_1_client_side_composition_tutorial
Fig. 110 04_function_1_client_side_composition_tutorial

その他

今回、URLは何も変化していない。 SEOを考慮するならば、URLと履歴管理について考えないといけない。

results matching ""

    No results matching ""