はじめに
Wijmo(ウィジモ)は、グレープシティがHTML/JavaScript環境に向けて提供しているJavaScriptライブラリで、WebサイトやWebアプリケーションで活用できるUI部品を利用者に提供します。
2015年1月に提供開始されたWijmoの新版「Wijmo 5」には、グリッド部品「FlexGrid」が含まれています。FlexGridはグレープシティが.NET環境向けに提供している同名コンポーネントのJavaScript版で、十分な実績を持つグリッド部品と類似の作法で、表データの表示・編集、ソートやフィルタなどさまざまな機能を利用することができます。
本記事ではWijmo 5のFlexGridが備える機能のいくつかを、サンプルを交えて説明していきます。
対象読者
- WebサイトやWebアプリケーションのレベルをワンランク上げたい方
- より軽量/高速なJavaScriptのUI部品を探している方
- Webページ上で表データを簡単に表示・操作したい方
必要な環境
Wijmo 5はECMAScript 5をサポートする、いわゆるモダンブラウザをターゲットにしており、WijmoのWebサイトでは以下のブラウザがサポート対象として案内されています。
- Internet Explorer:9以上
- Google Chrome:5以上
- Mozilla Firefox:4以上
- Safari:5以上
- Opera:12以上
今回は以下の環境で動作を確認しています。
-
Windows 7 64bit版
- Internet Explorer 11
なお本記事のサンプルコードは、AngularJS(バージョン1.2.1)およびWijmo 5のAngularJS連携機能を利用しています。
FlexGridの紹介
FlexGridはグレープシティが提供するグリッド部品で、現在では同社のコンポーネント製品「ComponentOne Studio」の一部として.NET向け(Windows フォーム、WPF、Silverlight、WinRTの各環境用が存在)に提供されています。
Wijmo 5のFlexGridはこれらのJavaScript版となり、.NET版のFlexGridが持つデータ表示や編集、ソートやフィルタ、ページングなどのデータ操作など、表型式データを取り扱うさまざまな機能をHTML/JavaScript環境でも使用することができます。
グリッドを表示するFlexGridコントロール
以下で、Wijmo 5が提供するFlexGridの機能と利用方法を段階を追って紹介していきます。
シンプルなグリッド表示
前回の連載記事でもFlexGridの単純なサンプルを紹介していますが、再度リスト1のサンプルでFlexGrid利用の概要を説明します。
<script type="text/javascript"> // Wijmoモジュール"wj"を指定して新規モジュールを作成 var myApp = angular.module("MyApp", ["wj"]); // モジュールにコントローラーを定義 myApp.controller("MyController", ["$scope", function($scope) { // スコープに変数を設定 ...(1) $scope.gridData = [ { "name":"iPhone 6", "vendor": "Apple", "ram": "1GB", "platform":"iOS", "version":"8.2" }, // 中略 ]; }]); </script> </head> <!-- 中略 --> <!-- FlexGrid表示 ...(2)--> <h3>FlexGrid</h3> <wj-flex-grid items-source="gridData" style="width:700px"> <wj-flex-grid-column header="製品名" binding="name"></wj-flex-grid-column> <wj-flex-grid-column header="メーカー" binding="vendor"></wj-flex-grid-column> <wj-flex-grid-column header="メモリ" binding="ram"></wj-flex-grid-column> <wj-flex-grid-column header="OS" binding="platform"></wj-flex-grid-column> <wj-flex-grid-column header="バージョン" binding="version"></wj-flex-grid-column> </wj-flex-grid> <!-- 以下略 -->
(1)がグリッドに表示するデータ変数gridDataの記述で、データ名とデータ内容の組をJavaScriptオブジェクトとして記述します。一方で(2)がFlexGridの記述です。wj-flex-gridディレクティブがグリッド全体を表し、items-source属性には(1)で記述したgridDataを指定します。wj-flex-grid-columnはグリッドの1列を表し、binding属性の値に対応するgridData内のデータ項目をグリッドに表示します。
リスト1を実行すると図2のようにデータがグリッドに表示されます。
プロパティを指定してFlexGridの動作をカスタマイズ
FlexGridコントロールには動作をカスタマイズできるプロパティが多数定義されています。FlexGridの主なプロパティを表1に示します。プロパティ名は、JavaScriptで指定する場合は先頭が小文字で単語の先頭が大文字(いわゆるキャメルケース)、AngularJSのディレクティブ(独自タグ)属性で指定する場合はハイフンで区切られた小文字(いわゆるチェインケース)で記述します。
プロパティ名 (JavaScript) |
プロパティ名 (ディレクティブ属性) |
内容 | デフォルト値 |
---|---|---|---|
isReadOnly | is-read-only | 読み取り専用にするかどうか | false |
allowAddNew | allow-add-new | 行を追加できるかどうか | false |
allowDelete | allow-delete | 行を削除できるかどうか | false |
allowSorting | allow-sorting | ヘッダセルをクリックしてソートできるかどうか | true |
selectionMode | selection-mode | セル選択モード | CellRange |
表1においてselectionModeには以下の値が設定できます。
定数 | 内容 |
---|---|
None | セル選択不可能 |
Cell | 1個のセルのみを選択可能 |
CellRange | 連続する複数のセルを選択可能 |
Row | 行単位で1行のみ選択可能 |
RowRange | 行単位で連続する複数行を選択可能 |
ListBox | 行単位で連続しない複数の行を選択可能 |
FlexGridにプロパティをディレクティブ属性で設定するサンプルをリスト2、3に示します。リスト2はプロパティ指定の記述です。
<h3>FlexGrid</h3> <wj-flex-grid items-source="gridData" style="width:700px" allow-add-new="true" allow-delete="true" allow-sorting="{{allowSorting}}" selection-mode="{{selectionMode}}"> <!-- 中略 --> </wj-flex-grid>
リスト2ではallow-add-newとallow-deleteの各プロパティに固定のプロパティ値を設定しています。一方でallow-sortingとselection-modeはそれぞれスコープに定義される変数allowSorting、selectionModeの値を参照するように記述しています。
プロパティを操作するHTML要素はリスト3です。ソート許可のチェックボックスとセル選択モードのプルダウンはng-model属性の指定により変数allowSorting、selectionModeと紐付け(バインド)されるため、コントロールの変更値が変数を介してFlexGridのallow-sorting、selection-modeプロパティに反映されます。
<h3>ソート許可</h3> <input type="checkbox" ng-model="allowSorting"/>ソート許可 <h3>セル選択モード</h3> <div> <select ng-model="selectionMode"> <option value="None">None</option> <option value="Cell">Cell</option> <option value="CellRange">CellRange</option> <option value="Row">Row</option> <option value="RowRange">RowRange</option> <option value="ListBox">ListBox</option> </select> </div>
リスト2、3を実行すると、行の追加・削除が可能なグリッドが表示されます。ソート許可とセル選択モードはチェックボックスやプルダウンで変更できます。
HTMLタグでFlexGridの表示をカスタマイズ
1列のグリッドを表すwj-flex-grid-columnディレクティブは、タグ内にHTMLタグを記述して表示をカスタマイズできます。リスト4に記述例を示します。
<wj-flex-grid-column width="32" is-read-only="true"><!-- 属性指定 ...(1)--> <img ng-src="img/{{$item.platform}}.png" /> <!-- 画像を参照 ...(2)--> </wj-flex-grid-column> <wj-flex-grid-column header="製品名" binding="name"></wj-flex-grid-column> <wj-flex-grid-column header="メーカー" binding="vendor"></wj-flex-grid-column> <wj-flex-grid-column header="メモリ" binding="ram"></wj-flex-grid-column> <wj-flex-grid-column header="OSバージョン"> {{$item.platform}} {{$item.version}} <!-- データ結合 ...(3) --> </wj-flex-grid-column>
1行分のデータが格納される$item変数を用いて、(2)ではAngularJSのimgディレクティブで画像ファイル($item.platformの値に応じて「iOS.png」または「Android.png」)を参照させています。また(3)では$item.platformと$item.versionの値を結合して表示させています。なお表示を整えるため、(1)ではwidthプロパティで列幅を、is-read-onlyプロパティで編集不可を設定しています。
リスト4を実行すると、(2)によりiOSとAndroidで異なるアイコンが表示され、(3)によりOS名とバージョンが結合して表示されます。
ICollectionViewインターフェースでページングやフィルタを実現
FlexGridはページングやフィルタなどのデータ操作を行う機能を備えます。以下では、データ操作のために提供されているICollectionViewインターフェースとその実装CollectionViewクラスの利用法を説明します。
FlexGridでデータ操作を行うためには、FlexGridに与えるデータを直接指定する代わりに、リスト5のようにデータ変数を引数に与えて生成したCollectionViewクラスのインスタンスを指定します。このように指定することで、ICollectionViewインターフェースが提供するデータ操作を行えるようになります。
// データを引数に与えてCollectionViewインスタンスを生成 $scope.gridData = new wijmo.collections.CollectionView(gridData); // gridDataはそのままFlexGridのitems-sourceに指定可能
ICollectionViewインターフェース(CollectionViewクラス)のAPIを利用したデータ操作例を以下でいくつか紹介します。
データ操作例1:ページング
ページングを実現するためには、リスト6のようにpageSizeプロパティに1ページあたりのデータ数を指定します。
// データを引数に与えてCollectionViewインスタンスを生成 $scope.gridData = new wijmo.collections.CollectionView(gridData); // ページング指定 $scope.gridData.pageSize = 3;
現在ページや全ページ数の表示、ページ移動のためには表3のメソッド・プロパティを利用します。
名称 | 内容 |
---|---|
moveToFirstPage() | 先頭ページに移動するメソッド |
moveToPreviousPage() | 1ページ前に移動するメソッド |
moveToNextPage() | 1ページ後に移動するメソッド |
moveToLastPage() | 最終ページに移動するメソッド |
pageIndex | 現在ページを表すプロパティ(先頭ページが0になる) |
pageCount | 全ページ数を表すプロパティ |
ページ操作・表示の実装例をリスト7に示します。
<button ng-click="gridData.moveToFirstPage()">先頭</button> <button ng-click="gridData.moveToPreviousPage()">前</button> {{gridData.pageIndex + 1 | number}} / {{gridData.pageCount | number}} <button ng-click="gridData.moveToNextPage()">次</button> <button ng-click="gridData.moveToLastPage()">最後</button>
リスト6、7を実行すると、データが3行ごとにページングされます。
データ操作例2:フィルタ
フィルタを実現するためには、filterメソッドにフィルタ処理を実装します。検索ワードでフィルタ処理を行う実装例をリスト8に示します。
// フィルタ値変数 ...(1) $scope.filterValue = ""; // データを引数に与えてCollectionViewインスタンスを生成 ...(2) $scope.gridData = new wijmo.collections.CollectionView(gridData); // フィルタ処理を実装 ...(3) $scope.gridData.filter = function(item) { // フィルタ未指定のときは無条件true if (!$scope.filterValue) { return true; } // フィルタ指定されているときはname属性とマッチング else { return item.name.indexOf($scope.filterValue) > -1; } }; // フィルタ変数(filterValue)が変更された時の処理 ...(4) var filterDescriptor; $scope.$watch('filterValue', function () { // timeout実行中の場合はいったん解除 if (filterDescriptor) { $timeout.cancel(filterDescriptor); } // 一定時間遅延後フィルタ適用 ...(5) filterDescriptor = $timeout(function () { $scope.gridData.refresh(); }, 1000); });
(1)は画面で入力された検索ワードが格納される変数です。(2)でデータからCollectionViewインスタンスを生成し、(3)でCollectionViewのフィルタ処理を実装します。フィルタ処理は「フィルタに合致した時にtrue、合致しない時にfalse」を返すようにします。ここではフィルタ値とデータのname属性を比較して部分一致した時にtrueを返しています。(4)ではフィルタの変数が変更された時に(検索ワードの入力とフィルタ適用処理が競合しないよう)一定の遅延時間後にフィルタを適用する(5)のrefreshメソッドを実行しています。遅延の処理にはAngularJSが提供する$timeoutを使用しています。
リスト8を実行すると、入力したフィルタ値と部分一致した製品名のデータだけがリストされるようになります。
データ操作例3:グループ化
グループ化を実現するためには、groupDescriptionsプロパティにグループ化の情報を表すGroupDescriptionクラスのインスタンスを指定します。実装例をリスト9に示します。
// グループを表す変数 ...(1) $scope.groupValue = ""; // データを引数に与えてCollectionViewインスタンスを生成 ...(2) $scope.gridData = new wijmo.collections.CollectionView(gridData); // グループ(group)が変更された時の処理 ...(3) var filterDescriptor; $scope.$watch('groupValue', function () { // 現在のgroupDescriptionsをクリア ...(4) $scope.gridData.groupDescriptions.clear(); if ($scope.groupValue.length > 0) { // グループ名を取得してgroupDescriptionsに設定 ...(5) var groupNames = $scope.groupValue.split(','); angular.forEach(groupNames, function(groupName, i) { var groupDesc = new wijmo.collections.PropertyGroupDescription(groupName); $scope.gridData.groupDescriptions.push(groupDesc); }); } });
(1)は選択されたグループの値に対応する変数で、データの列名(「name」「version」など)が格納されます。(2)でデータからCollectionViewインスタンスを生成し、(3)でグループの変数が変更された時にgroupDescriptionsを更新してグループ表示を適用しています。まず(4)ですでに適用されたgroupDescriptionsをクリアし、(5)ではカンマ区切りで指定されたグループ名のそれぞれからグループを指定しています。ここでPropertyGroupDescriptionはGroupDescriptionクラスの子クラスで、グループ名(データの列名)でグループを指定できます。なおループ処理にはAngularJSが提供するangular.forEachメソッドを使用しています。
リスト9を実行すると、指定されたデータ列でデータをグループ表示できます。
まとめ
本記事では、グレープシティのJavaScriptライブラリ「Wijmo 5」が提供するグリッド部品「FlexGrid」について、機能や使用法をサンプルコードとともに紹介しました。FlexGridのAPIや、ICollectionViewインターフェースによるデータ操作の仕組みは、従来より提供されている.NET版のFlexGridを下敷きにしているため、.NET版の利用経験を生かして開発が可能です。経験がない利用者にとっても、.NET版で実績のあるAPIを用いてHTML/JavaScript環境でグリッド部品を利用できるメリットがあります。
次回記事ではチャートやゲージ、入力部品など、Wijmo 5が備えるFlexGrid以外のJavaScriptコントロールについて説明します。