UMD版Hexabase JavaScript SDKを使ってTodoアプリを作る（タスク一覧表示・追加・削除）

[Hexabase（ヘキサベース）](https://www.hexabase.com/)は企業においても安心して利用できるBaaS（Backend as a Service）を提供しています。多くのBaaSがそうであるように、主にフロントエンド開発者に利用してもらいたいと考えています。そこで現在、TypeScript SDKの開発が進められています。

元々TypeScriptで作られていることもあって、Next.jsやVue.jsなどでimportして利用することができます。しかし、もっと普通のWebアプリケーションなどで使う際には、CDN経由で利用したいと考える方もいるでしょう。そこで、UMD版Hexabase JavaScript SDKを作成しました。

今回は、そのUMD版Hexabase JavaScript SDKを使ったTodoアプリのデモを紹介します。まずはタスク一覧の表示とタスクの追加、そして削除を行えるようにしました。

## デモ

デモはこちらのURLで体験できます。

[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/348149e7-3f13-e621-bd64-cffd38cb8a1e.png)](https://jsfiddle.net/moongift/ohy3zwv1/75/)


## SDKの読み込み

SDKは下記URLで読み込めます。

```html
<script src="https://cdn.jsdelivr.net/npm/@hexabase/hexabase-js@latest/dist/umd/hexabase.min.js"></script>
```

バージョン指定する場合は、以下のようになります。メジャーバージョンが上がらない限りはlatest指定をお勧めします。

```html
<script src="https://cdn.jsdelivr.net/npm/@hexabase/hexabase-js@2.0.6/dist/umd/hexabase.min.js"></script>
```

モジュールとして使う場合には、以下のようになります。

```html
<script type="module">
import hexabase from 'https://cdn.jsdelivr.net/npm/@hexabase/hexabase-js@latest/+esm'
</script>
```

## SDKの初期化

SDKは以下のようコードで初期化します。これさえ終われば、後はTypeScriptと同じように使えます。

```javascript
const { HexabaseClient } = hexabase;
const client = new HexabaseClient();
```

## ベースのプロジェクト

今回はHexabaseで提供しているTODO管理サンプルを使っています。

![1891 app.hexabase.com - 1226172218.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/112785dc-c212-cbdf-3820-24c937c1e1bf.jpeg)


## HTMLについて

HTMLはBootstrapを使って、以下のように作成しています。上半分が既存タスクの表示、下半分はタスクの追加用フォームになっています。

```html
<div class="container">
  <div class="row justify-content-md-center">
    <div class="col-10">
			<!-- タスク一覧 -->
      <table class="table">
        <thead>
          <tr>
            <th scope="col">タスク</th>
            <th scope="col">担当者名</th>
            <th scope="col">カテゴリ</th>
            <th scope="col">ステータス</th>
            <th scope="col">アクション</th>
          </tr>
        </thead>
        <tbody></tbody>
      </table>
			<!-- タスク追加用フォーム -->
      <form>
        <div class="row g-3">
          <div class="col">
            <input type="text" class="form-control" name="Title" aria-describedby="emailHelp" value="新しいタスク">
          </div>
          <div class="col">
            <input type="text" class="form-control" name="Assignee" value="担当者名">
          </div>
          <div class="col">
            <select name="Category" class="form-control"></select>
          </div>
          <div class="col">
            <button type="submit" id="add" class="btn btn-primary" disabled>追加</button>
          </div>
        </div>
      </form>
    </div>
  </div>
</div>
```

### 初期設定

まずコード内で使う変数、DOMを定義します。

```javascript
// 認証用のメールアドレスとパスワード
const email = 'demo5@moongift.jp';
const password = 'K4c%j%vzR7sQKS$u&Uo%';

// Hexabaseのワークスペース、プロジェクト、ワークスペースのID
const workspaceId = '644f6e5ab30d853869ec919f';
const projectId = '650a30501222568b1ae7a2c2';
const datastoreId = '65895ba97b4300d37757d562';

// 複数の処理で使う変数用
const params = {
	datastore: null, // データストア
  items: [], // 既存タスク一覧
};

// DOM
const addButton = document.querySelector('#add');
const table = document.querySelector('.table tbody');
```

## 初期表示処理

初期表示の処理は以下のようになります。初期設定、データの読み込み、そしてフォームへの値設定となります。

```js
// 画面が読み込まれたときの処理
(async () => {
  await init();
  load();
  await makeForm();
})();
```

### 初期設定

初期設定用の `init` 関数ではログインやワークスペース・プロジェクト・データストアの取得を行っています。

```javascript
// 初期設定
const init = async () => {
  // ログイン
  const res = await client.login({email, password});
  // ワークスペース・プロジェクト・データストアの取得
  await client.setWorkspace(workspaceId);
  const project = await client.currentWorkspace.project(projectId);
  params.datastore = await project.datastore(datastoreId);  
  // 追加ボタンを押せるようにする
  addButton.disabled = false;
};
```

### データの読み込み

`load` 関数は既存のタスク一覧を読み込み、テーブルに表示します。

```javascript
// 既存のアイテム一覧を取得する処理
const load = async () => {
  const query = client.query(projectId);
  const items = await query
    .from(datastoreId)
    .select('*');
  params.items = items;
  // 表示更新
  showTable();
};
```

`showTable` 関数は、取得したアイテム一覧をテーブルに表示します。また、削除ボタンのイベントリスナーも設定しています。

```javascript
// タスク一覧の更新と、タスクへのアクション設定
const showTable = () => {
  // params.itemsに沿って、表示を更新
  table.innerHTML = params.items.map(item => `
    <tr data-id="${item.id}">
  	  <td>${item.get('Title')}</td>
      <td>${item.get('Assignee')}</td>
      <td>${item.get('Category').ja}</td>
      <td>${item._status ? item._status.name : item.statusLabel}</td>
      <td>
    	<span class="delete">🗑️</span>
      </td>
    </tr>`).join('');
  
  // 削除のイベントリスナー
  table.querySelectorAll('.delete').forEach(dom => {
  	dom.addEventListener('click', (e) => {
  		const id = e.target.closest('tr').getAttribute('data-id');
  		deleteItem(id);
    });
  })
};
```

### フォームの作成

`makeForm` 関数は、フォームの `select` タグに対して、Hexabaseで設定しているオプションを取得し、描画します。

`ja` は日本語で、 `en` に英語が設定されています。

```javascript
// フォームの作成処理
const makeForm = async () => {
  // ドロップダウンの項目を取得
  const field = await params.datastore.field('Category');
  // オプション項目を取得
  const options = await field.options();
  // HTMLに反映
  const html = options.map(option => `
  	<option id="${option.id}">${option.value.ja}</option>
  `);
  document.querySelector('form [name="Category"]').innerHTML = html;
}
```

## タスクの追加

フォーム送信時のイベントで、タスクの追加を行います。 `datastore.item()` にて新規アイテムが作成できます。

後は、その `item` に値をセットして保存するだけです。

```javascript
// フォームの送信イベント
document.querySelector('form').onsubmit = async (e) => {
  e.preventDefault();
  // 新しいアイテムを作成
  const item = await params.datastore.item();
  // アイテムに値をセット
  for (const input of Array.from(e.target.elements)) {
  	if (input.name === '') continue;
    item.set(input.name, input.value);
  }
  // アイテムの保存
  await item.save();
  // 一覧に追加
  params.items.push(item);
  // 再描画
  showTable();
};
```

## タスクの削除

タスクを削除する際には、該当する `item` の `delete` メソッドを呼び出します。削除したら、 `params.items` からも削除して、再描画します。

```javascript
// アイテムの削除処理
const deleteItem = async (id) => {
  // 該当するアイテムを探す
  const item = params.items.find(item => item.id === id);
  // アイテムの削除
  await item.delete();
  // リストを更新
  params.items = params.items.filter(item => item.id !== id);
  // 再描画
  showTable();
};
```

## まとめ

今回はUMD版Hexabase JavaScript SDKを使って、Todoアプリを作成するデモを紹介しました。UMD版Hexabase JavaScript SDKは、CDN経由で利用できるため、jQueryなど普通のWebアプリケーションでも利用できます。また、TypeScript SDKと同じように使えるため、TypeScript SDKを使っている方でも移行が容易です。

ぜひHexabaseを使ってWebアプリケーション開発を行ってください。

[Hexabase \| 新規事業向け開発・競争領域でのDX実現をサポート](https://www.hexabase.com/)