はじめに
Wijmo(ウィジモ)は、グレープシティがHTML/JavaScript環境に向けて提供しているJavaScriptライブラリで、WebサイトやWebアプリケーションで活用できるUI部品を利用者に提供します。現行版はECMAScript 5に対応した「Wijmo 5」です。
2017年5月に、Wijmoのアップデート「2017J v1」がリリースされ、さまざまな新機能が追加されました。本記事ではこのうち、MultiAutoCompleteコントロールを紹介します。MultiAutoCompleteは複数項目選択のUI部品で、キーボードで入力した文字列に一致する項目リストや、全項目の一覧ドロップダウンリストから、素早く選択できます。
参考 Wijmoの入力コントロール
WijmoではMultiAutoCompleteのほか、表1のような入力コントロールが提供されており、状況に応じて使い分けできます。詳細は入力コントロールに関するWijmoのドキュメントを参照してください。
| 名前 | 概要 |
|---|---|
| AutoComplete | MultiAutoCompleteと類似した単一項目選択のUI部品 |
| MultiSelect | ドロップダウンリストのチェックボックスで複数選択 |
| ComboBox | 入力値を自動補完する単一選択ドロップダウンリスト |
対象読者
- WebサイトやWebアプリケーションのレベルをワンランク上げたい方。
- より軽量/高速なJavaScriptのUI部品を探している方。
- 最新アップデートで何ができるかを確認したいWijmo 5ユーザーの方。
必要な環境
Wijmo 5はECMAScript 5に対応する、いわゆるモダンブラウザをサポートします。対応ブラウザはWijmoのWebサイトで案内されています。
Wijmo 5はJavaScriptのライブラリで、それ単体で利用できるほか、Angular(AngularJS 1/Angular 2以降)、Knockout.js、React、Vue.js(1/2)といったJavaScriptフレームワークと組み合わせて利用できます。本記事では、Wijmo 5とAngular(バージョン4)の組み合わせを利用します。Wijmo 5とAngularを組み合わせて利用する方法については、過去記事も参照してください。
今回は以下の環境で動作を確認しています。
-
Windows 10 64bit版
- Wijmo 5 5.20171.293 体験版
- Angular バージョン4
- Node.js v6.11.0 64bit版
- Microsoft Edge 40.15063.0.0
Angularの開発ではTypeScript(変換してJavaScriptを生成する、いわゆるAltJS言語)を利用する場合が多く、本記事のサンプルもTypeScriptで記述しています。
なお、本記事のサンプルコードを実行するには、Wijmoのダウンロードファイルからサンプルコードのwijmo_samplesフォルダーにWijmo 5のフォルダーを展開して「wijmo_download」と名前を変更したあと、各サンプルコードのフォルダーで「npm install」「npm start」コマンドを実行してください。
はじめてのMultiAutoComplete
最初に、MultiAutoCompleteの基本的な実装と画面操作方法を、図3のサンプルで説明します。
MultiAutoCompleteの基本的な実装
MultiAutoCompleteを利用するには、まず、ルートモジュール定義ファイルapp.module.tsで、Angular用のMultiAutoComplete(WjMultiAutoCompleteクラス)を含むモジュールWjInputModuleを読み込みます。
import { WjInputModule } from "wijmo/wijmo.angular2.input";
(略)
@NgModule({
imports: [ BrowserModule, WjInputModule ],
ルートコンポーネントファイルapp.component.tsでは、リスト2のように、WjMultiAutoCompleteクラスに対応する<wj-multi-auto-complete>タグをテンプレートに記述します。
<wj-multi-auto-complete [itemsSource]="items"> ...(1) </wj-multi-auto-complete>
リスト2(1)のitemsSource属性に、表示する項目が格納された配列の変数名を設定します。ここで設定した「items」は、コンポーネントにリスト3のように記述します。
items = [ "nttdocomo", "ntteast", (略) ];
MultiAutoCompleteの操作方法
MultiAutoCompleteのテキストボックスに文字列を入力すると、部分一致する項目がリスト表示されるので、リストから選択して入力できます。
フォーカスが当たっている状態でAlt + 上下キーを押下すると、すべての項目をドロップダウン表示して選択することもできます。
MultiAutoCompleteは、キーボードショートカットで効率よく操作できるように設計されています。サポートされているショートカットを表2に示します。
| ショートカット | 動作 |
|---|---|
| Space、F4、Alt + 上下 | ドロップダウンリストを表示 |
| 上下 | ドロップダウンリストを表示せずに前後の項目を表示 |
| Enter | ドロップダウンリストを閉じて項目を追加 |
| Tab | ドロップダウンリストを閉じずに項目を追加 |
| Esc | 項目を追加せずにドロップダウンリストを閉じる |
| 左右 | すでに入力されている項目を選択 |
| BackSpace、Delete | 選択した項目を削除 |
選択された項目の取得
MultiAutoCompleteで選択された項目は、selectedItemやselectedItemsプロパティで取得できます。図6のサンプルで説明します。
ルートコンポーネントのテンプレートはリスト4のようになります。
<wj-multi-auto-complete
#multiAutoComplete1 ...(1)
[itemsSource]="items">
</wj-multi-auto-complete>
<h4>選択された項目</h4>
<ul>
<li *ngFor="let item of multiAutoComplete1.selectedItems"><!--(2)-->
{{item}}
</li>
</ul>
<h4>ドロップダウン選択中の項目</h4>
<div>{{multiAutoComplete1.selectedItem}}</div><!--(3)-->
(1)では、MultiAutoCompleteに「multiAutoComplete1」と名前を付けて、他の個所から参照できるようにしています。
MultiAutoCompleteで選択された項目は、selectedItemsプロパティから配列で取得できます。このサンプルでは(2)のように、Angularの*ngForディレクティブでselectedItemsプロパティ配列の各要素を取得して、画面にリスト表示しています。
一方、selectedItemプロパティは、画面表示されたドロップダウンで選択中の値に対応します。Alt + 上下キーでドロップダウンを表示して、カーソルで項目を選択すると、カーソルが当たっている項目(図6では「softbank」)が(3)の部分に表示されます。
CollectionViewを使って複数の属性を持った項目を表示
ここまでのサンプルでは、itemsSource属性に単純な配列を設定してきましたが、複数の属性を持ったオブジェクトの配列を、Wijmoが提供するCollectionViewの形式で設定することもできます。キーと名前、証券コードを含むデータのCollectionViewから項目を選択する、図7のサンプルで説明します。
まず、項目のデータを表すCollectionViewを生成して、変数itemsに格納します。キーを「key」に、名前を「name」に、証券コードを「security」に、それぞれ設定しています。
items: CollectionView = new CollectionView([
{ key: "nttdocomo", name: "NTTドコモ", security: "9437" },
{ key: "nttdata", name: "NTTデータ", security: "9613" },
{ key: "kddi", name: "KDDI", security: "9433" },
{ key: "softbank", name: "ソフトバンクグループ", security: "9984" },
{ key: "yahoo", name: "ヤフー", security: "4689" }
]);
リスト5の内容を表示するテンプレートは、リスト6のようにします。
<wj-multi-auto-complete
#multiAutoComplete1
[itemsSource]="items" ...(1)
[displayMemberPath]="'name'" ...(2)
[searchMemberPath]="'key,security'"> ...(3)
</wj-multi-auto-complete>
<h4>選択された項目</h4>
<ul>
<li *ngFor="let item of multiAutoComplete1.selectedItems">
{{item | json}} <!--(4)-->
</li>
</ul>
(1)のitemsSource属性に、CollectionViewの変数itemsを設定します。itemsSource属性には、単純な配列とCollectionViewのどちらも設定できます。
(2)のdisplayMemberPath属性は、オブジェクト属性のうち、画面に表示するものの名前を設定します。ここでは名前が格納された「name」を設定しています。
displayMemberPathで設定されたオブジェクト属性は、テキストボックス入力内容との部分一致が自動で行われますが、(3)のsearchMemberPath属性に、部分一致の対象とするオブジェクト属性を追加で設定できます。カンマ区切りで複数設定でき、ここではキー「key」と、証券コード「security」を設定しています。キーや証券コードを入力して候補を表示する操作が実現できます。
なお、itemsSourceにCollectionViewを設定した場合、前述のselectedItemsやselectedItemプロパティには、選択した項目のオブジェクトが設定されます。このサンプルでは、リスト6(4)で、selectedItemsから取得されたデータを、AngularのPipesでJSON文字列に変換して画面表示しています。Pipesについては、Angularの解説記事も参考にしてください。
itemsSourceFunctionで検索処理をカスタマイズ
MultiAutoCompleteでは、検索する項目をitemsSourceに設定する代わりに、項目を検索する処理をitemsSourceFunction属性に設定できます。項目の検索に外部WebAPIを利用するなど、検索処理をカスタマイズしたい場合に便利です。ここではカスタマイズした検索処理の実装例を、在庫が残っている本だけを検索する書籍検索のサンプル(図9)で説明します。
まず、<wj-multi-auto-complete>タグのitemsSourceFunction属性に、検索処理を行うメソッド名「searchItem」を、リスト7(1)のように設定します。
<wj-multi-auto-complete [itemsSourceFunction]="searchItem" ...(1) [displayMemberPath]="'name'"> </wj-multi-auto-complete>
リスト7に対応するコンポーネントの実装は、リスト8のようになります。
export class AppComponent {
// 書籍のデータ ...(1)
item: CollectionView = new CollectionView([
{ name: "はじめてのWijmo", stock: 20 },
{ name: "TypeScript大全", stock: 15 },
{ name: "これから始めるAngular", stock: 0 },
{ name: "React実践活用", stock: 0 },
{ name: "乗り遅れないECMAScript", stock: 20 }
]);
// searchItemメソッド内のthisをコンポーネント自身に設定 ...(2)
constructor() {
this.searchItem = this.searchItem.bind(this);
}
// 検索処理メソッド ...(3)
searchItem(query: string, max: number, callback: Function) {
setTimeout( () => { // API呼び出しの通信遅延をsetTimeoutで表現 ...(4)
// 在庫があって、名前が一致するものを抽出
this.item.filter = function (item: any) {
return (item.name.toLowerCase().indexOf(query) >= 0 // ...(5)
&& item.stock > 0);
}
// フィルター結果を配列に格納 ...(6)
var array: any = [];
for (var i = 0; i < Math.min(this.item.itemCount, max); i++) {
array.push(this.item.items[i]);
}
// callbackに配列を渡す ...(7)
callback(array);
}, 1000);
}
}
(1)が検索対象の書籍データです。名前を「name」、在庫数を「stock」に設定します。stockが0になっている「これから始めるAngular」と「React実践活用」は在庫切れです。
コンポーネントのコンストラクタ(2)では、後述するsearchItemメソッド内で、コンポーネント自身をthisとして参照できるように設定しています。
検索処理を行うsearchItemメソッドは(3)です。このsearchItemのように、itemsSourceFunctionに設定したメソッドには、表3のような引数が渡されます。
| 引数の順番 | 型 | 意味 | searchItemメソッドでの変数名 |
|---|---|---|---|
| 1 | 文字列 | テキストボックスに入力された検索文字列 | query |
| 2 | 数字 | ドロップダウンに表示する項目の最大数 | max |
| 3 | 関数 | 検索結果を渡すコールバック関数 | callback |
これらの引数を用いて、検索処理を実行します。例えば「検索文字列と項目の最大数をWebAPIに与えて結果を取得する」といったことができます。
ここでは(5)で、CollectionViewのフィルター機能を利用して「検索文字列と名前が部分一致して、かつ在庫がある書籍」を検索します。CollectionViewのfilterプロパティに設定した関数で、条件に合致するときにtrue、しないときにfalseを返すように実装すると、データをフィルターできます。フィルター機能の詳細は公式ドキュメントも参考にしてください。なお、item.nameをtoLowerCaseメソッドで小文字にして比較しているのは、itemsSourceFunctionの仕様上、入力文字列が小文字に変換されるためです。
フィルターされたデータを(6)で配列に詰めなおして、その配列を引数として(7)でコールバック関数を実行しています。コールバック関数が実行された時点で、画面上に検索結果が表示されます。
なお、このサンプルでは、通信の遅延を模擬するためのsetTimeout関数(4)で、コンポーネント自身をthisとして参照するためにアロー関数を利用しています。アロー関数の詳細はMozillaのドキュメントも参考にしてください。
MultiAutoCompleteの活用例と優位性
MultiAutoCompleteコントロールは、キーボードやマウスの操作で、素早く複数の選択肢を入力するときに優位性を発揮します。例えば、図10のようなアンケートフォームでの利用を考えてみます。
MultiAutoCompleteを利用せずに複数選択のフォームを提供するには、項目ごとにチェックボックスを並べるか、複数選択可能なセレクトボックスを作る方法が考えられます。しかし、前者は選択肢が増えるごとに場所をとり、美しい表示とは言い難い状態です。後者は複数選択のためにCtrlキーやShiftキーを押しながらクリックする必要があり、操作が直感的ではありません。MultiAutoCompleteを利用すれば、より洗練された画面表示や操作感を利用者に提供できます。
まとめ
本記事では、グレープシティのJavaScriptライブラリWijmo 5に新たに追加されたMultiAutoCompleteコントロールについて、利用方法を説明しました。MultiAutoCompleteコントロールを利用すれば、キーボードからの直接入力、ドロップダウンリストからの選択といった複数の方法で項目を選択できます。HTMLの標準コントロールよりも、見やすく使いやすいWebページを作ることができます。

