Shoeisha Technology Media

CodeZine(コードジン)

記事種別から探す

「Wijmo(ウィジモ) 5」のMultiAutoCompleteコントロールで複数項目を素早く選択

ECMAScript 5に準拠した高速・軽量なJavaScript UIライブラリ「Wijmo 5」の活用 第12回

  • LINEで送る
  • このエントリーをはてなブックマークに追加

 本連載では、グレープシティが提供するJavaScriptライブラリWijmo(ウィジモ)について、サンプルとともに利用例を紹介します。2017年5月の「2017J v1」アップデートで追加されたWijmoの新機能のうち、前回はTreeViewを紹介しましたが、今回は複数項目を素早く選択できるMultiAutoCompleteコントロールの利用法を説明します。

はじめに

 Wijmo(ウィジモ)は、グレープシティがHTML/JavaScript環境に向けて提供しているJavaScriptライブラリで、WebサイトやWebアプリケーションで活用できるUI部品を利用者に提供します。現行版はECMAScript 5に対応した「Wijmo 5」です。

 2017年5月に、Wijmoのアップデート「2017J v1」がリリースされ、さまざまな新機能が追加されました。本記事ではこのうち、MultiAutoCompleteコントロールを紹介します。MultiAutoCompleteは複数項目選択のUI部品で、キーボードで入力した文字列に一致する項目リストや、全項目の一覧ドロップダウンリストから、素早く選択できます。

図1 MultiAutoCompleteコントロールの例(Wijmoサンプルより)
図1 MultiAutoCompleteコントロールの例(Wijmoサンプルより)

参考 Wijmoの入力コントロール

 WijmoではMultiAutoCompleteのほか、表1のような入力コントロールが提供されており、状況に応じて使い分けできます。詳細は入力コントロールに関するWijmoのドキュメントを参照してください。

表1 MultiAutoCompleteに類似した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」コマンドを実行してください。

図2 サンプルコードのフォルダにWijmo 5を展開
図2 サンプルコードのフォルダにWijmo 5を展開

はじめてのMultiAutoComplete

 最初に、MultiAutoCompleteの基本的な実装と画面操作方法を、図3のサンプルで説明します。

図3 MultiAutoCompleteの表示(001-basic)
図3 MultiAutoCompleteの表示(001-basic)

MultiAutoCompleteの基本的な実装

 MultiAutoCompleteを利用するには、まず、ルートモジュール定義ファイルapp.module.tsで、Angular用のMultiAutoComplete(WjMultiAutoCompleteクラス)を含むモジュールWjInputModuleを読み込みます。

リスト1 MultiAutoCompleteのモジュール設定(001-basic/src/app/app.module.ts)
import { WjInputModule } from "wijmo/wijmo.angular2.input";
(略)
@NgModule({
  imports:      [ BrowserModule, WjInputModule ],

 ルートコンポーネントファイルapp.component.tsでは、リスト2のように、WjMultiAutoCompleteクラスに対応する<wj-multi-auto-complete>タグをテンプレートに記述します。

リスト2 テンプレートにMultiAutoCompleteを記述(001-basic/src/app/app.component.ts)
<wj-multi-auto-complete
  [itemsSource]="items"> ...(1)
</wj-multi-auto-complete>

 リスト2(1)のitemsSource属性に、表示する項目が格納された配列の変数名を設定します。ここで設定した「items」は、コンポーネントにリスト3のように記述します。

リスト3 表示する項目の配列(001-basic/src/app/app.component.ts)
items = [
  "nttdocomo",
  "ntteast",
(略)
];

MultiAutoCompleteの操作方法

 MultiAutoCompleteのテキストボックスに文字列を入力すると、部分一致する項目がリスト表示されるので、リストから選択して入力できます。

図4 入力文字列に一致する候補を表示(001-basic)
図4 入力文字列に一致する候補を表示(001-basic)

 フォーカスが当たっている状態でAlt + 上下キーを押下すると、すべての項目をドロップダウン表示して選択することもできます。

図5 すべての項目をドロップダウン表示(001-basic)
図5 すべての項目をドロップダウン表示(001-basic)

 MultiAutoCompleteは、キーボードショートカットで効率よく操作できるように設計されています。サポートされているショートカットを表2に示します。

表2 MultiAutoCompleteのキーボードショートカット
ショートカット 動作
Space、F4、Alt + 上下 ドロップダウンリストを表示
上下 ドロップダウンリストを表示せずに前後の項目を表示
Enter ドロップダウンリストを閉じて項目を追加
Tab ドロップダウンリストを閉じずに項目を追加
Esc 項目を追加せずにドロップダウンリストを閉じる
左右 すでに入力されている項目を選択
BackSpace、Delete 選択した項目を削除

選択された項目の取得

 MultiAutoCompleteで選択された項目は、selectedItemやselectedItemsプロパティで取得できます。図6のサンプルで説明します。

図6 選択された項目を取得(002-getvalue)
図6 選択された項目を取得(002-getvalue)

 ルートコンポーネントのテンプレートはリスト4のようになります。

リスト4 選択された項目を取得する実装(002-getvalue/src/app/app.component.ts)
<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のサンプルで説明します。

図7 CollectionViewの項目リストから入力(003-collectionview)
図7 CollectionViewの項目リストから入力(003-collectionview)

 まず、項目のデータを表すCollectionViewを生成して、変数itemsに格納します。キーを「key」に、名前を「name」に、証券コードを「security」に、それぞれ設定しています。

リスト5 CollectionViewで項目を定義(003-collectionview/src/app/app.component.ts)
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のようにします。

リスト6 CollectionViewの項目を表示するテンプレート(003-collectionview/src/app/app.component.ts)
<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」を設定しています。キーや証券コードを入力して候補を表示する操作が実現できます。

図8 証券コードを入力して候補を表示(003-collectionview)
図8 証券コードを入力して候補を表示(003-collectionview)

 なお、itemsSourceにCollectionViewを設定した場合、前述のselectedItemsやselectedItemプロパティには、選択した項目のオブジェクトが設定されます。このサンプルでは、リスト6(4)で、selectedItemsから取得されたデータを、AngularのPipesでJSON文字列に変換して画面表示しています。Pipesについては、Angularの解説記事も参考にしてください。

itemsSourceFunctionで検索処理をカスタマイズ

 MultiAutoCompleteでは、検索する項目をitemsSourceに設定する代わりに、項目を検索する処理をitemsSourceFunction属性に設定できます。項目の検索に外部WebAPIを利用するなど、検索処理をカスタマイズしたい場合に便利です。ここではカスタマイズした検索処理の実装例を、在庫が残っている本だけを検索する書籍検索のサンプル(図9)で説明します。

図9 itemsSourceFunctionの利用例(004-func)
図9 itemsSourceFunctionの利用例(004-func)

 まず、<wj-multi-auto-complete>タグのitemsSourceFunction属性に、検索処理を行うメソッド名「searchItem」を、リスト7(1)のように設定します。

リスト7 検索処理メソッド名を設定するテンプレート(004-func/src/app/app.component.ts)
<wj-multi-auto-complete
  [itemsSourceFunction]="searchItem" ...(1)
  [displayMemberPath]="'name'">
</wj-multi-auto-complete>

 リスト7に対応するコンポーネントの実装は、リスト8のようになります。

リスト8 検索処理を含むコンポーネント(004-func/src/app/app.component.ts)
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のような引数が渡されます。

表3 itemsSourceFunctionに設定するメソッドの引数
引数の順番 意味 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のようなアンケートフォームでの利用を考えてみます。

図10 MultiAutoCompleteで作ったアンケートフォーム(005-questionnaire)
図10 MultiAutoCompleteで作ったアンケートフォーム(005-questionnaire)

 MultiAutoCompleteを利用せずに複数選択のフォームを提供するには、項目ごとにチェックボックスを並べるか、複数選択可能なセレクトボックスを作る方法が考えられます。しかし、前者は選択肢が増えるごとに場所をとり、美しい表示とは言い難い状態です。後者は複数選択のためにCtrlキーやShiftキーを押しながらクリックする必要があり、操作が直感的ではありません。MultiAutoCompleteを利用すれば、より洗練された画面表示や操作感を利用者に提供できます。

まとめ

 本記事では、グレープシティのJavaScriptライブラリWijmo 5に新たに追加されたMultiAutoCompleteコントロールについて、利用方法を説明しました。MultiAutoCompleteコントロールを利用すれば、キーボードからの直接入力、ドロップダウンリストからの選択といった複数の方法で項目を選択できます。HTMLの標準コントロールよりも、見やすく使いやすいWebページを作ることができます。

参考資料

  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

  • WINGSプロジェクト  吉川 英一(ヨシカワ エイイチ)

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2017年5月時点での登録メンバは52名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂き...

  • 山田 祥寛(ヤマダ ヨシヒロ)

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XMLD...

All contents copyright © 2005-2018 Shoeisha Co., Ltd. All rights reserved. ver.1.5