機能拡張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-box
のsubmit
(カスタム)イベントをteam-product-list
やteam-inspire-list
へ伝搬します。
フラグメント
team-search-box
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
イベントによって更新される。
結果
その結果、次のような画面が表示される。
その他
今回、URLは何も変化していない。 SEOを考慮するならば、URLと履歴管理について考えないといけない。