[Wijmo入門]Wijmoを支えるデータ管理クラス「CollectionView」の基本

Wijmo(ウィジモ)」は業務アプリケーションの様々な要件に対応できるUI部品を備えたJavaScriptライブラリです。

Wijmoでは「FlexGrid(フレックスグリッド)」や「FlexChart(フレックスチャート)」といった非常に高機能なUIコントロールが利用可能ですが、それらで使用するデータを管理する機能として「CollectionView(コレクションビュー)」という機能を提供しています。
今回の記事ではWijmoを陰で支えるデータ管理クラス「CollectionView」について解説します。

開発環境

今回は開発環境として以下を使用します。

CollectionViewとは

XAMLプラットフォームのCollectionView

CollectionViewといえば、WPFなどXAMLプラットフォームでの開発経験がある方は、 .NETのデータ管理機能としてご存じの方も多いかと思います。

WPFなどで使用できるCollectionViewでは、その名の通りコレクションのビューの役割を担っており、要素の並び替えやフィルタ、グルーピングなどを行うことが出来ます。

Wijmoが提供するCollectionViewはこのXAMLプラットフォームのCollectionViewのJavaScript版となっており、 .NETでの開発経験がある方には馴染みのある機能となっています。

WijmoのCollectionView

WijmoのCollectionViewも同様にMVVMフレンドリな方法で、データをUI要素に連結することでき、主に以下の3つのインターフェースを実装しています。

WijmoのCollectionViewが実装するインタフェース
ICollectionView現在のレコードの管理、カスタムソート、フィルタ処理、およびグループ化を提供します。
IEditableCollectionView項目を編集、追加、および削除するためのメソッドを提供します。
IPagedCollectionViewページングを提供します。

CollectionViewを使ってみよう!

それでは早速CollectionViewを使ってみましょう。CollectionViewが真価を発揮するのはWijmoのコントロールと一緒に使う場合ですが、一般的なJavaScriptの連想配列やJSONデータのソートやフィルタリングにも使用することができます。

今回は以下のファイルを用意して、CollectionViewの機能を試してみます。

index.htmlページ本体。このページの要素として各種コントロールを配置します
app.jsCollectionViewの各種機能を使用するためのコードを記載します

Wijmoの参照

まずはCollectionViewを使うのに必要なライブラリの参照設定をHTMLファイルに追加します。CollectionViewはUIを伴わない機能ですが、Wijmoの機能はブラウザ上で使用することを想定して作られているので、HTMLファイルを用意します。
また、Wijmoのモジュールのほか、CollectionViewの各種処理を記載する「app.js」への参照も追加し、さらにulタグでCollectionViewで操作した結果を表示するリストを定義します。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>CollectionView入門</title>

    <!-- Wijmoのコアモジュール(必須) -->
    <script src="scripts/wijmo.min.js"></script>
    <script src="scripts/app.js"></script>
</head>
<body>
    <ul id="product_list"></ul>
</body>
</html>

上記のように直接プロジェクトにモジュールを配置する方法のほか、CDNから参照したり、npmパッケージを使用したりすることもできます。

製品ヘルプの「Wijmoの参照」を見る
製品ヘルプの「npmによるWijmoの参照」を見る

初期化処理とデータの表示

次に「app.js」に連想配列のデータの定義と、それらをCollectionViewを使ってソート、フィルタする処理を記述します。今回は「unitprice」が「200」より大きい項目を降順に並び替えます。
並び替えた結果は、createElementを使用してリストに追加していきます。

let products = [
    { productId: 1, productName: "果汁100% オレンジ", unitPrice: 200 },
    { productId: 2, productName: "果汁100% グレープ", unitPrice: 200 },
    { productId: 3, productName: "果汁100% レモン", unitPrice: 1000 },
    { productId: 4, productName: "果汁100% ピーチ", unitPrice: 1000 },
    { productId: 5, productName: "コーヒーマイルド", unitPrice: 1000 },
    { productId: 6, productName: "コーヒービター", unitPrice: 1000 },
    { productId: 7, productName: "コーヒーミルク", unitPrice: 500 },
    { productId: 8, productName: "ピリピリ ビール", unitPrice: 100 },
    { productId: 9, productName: "オタル白ラベル", unitPrice: 2500 },
    { productId: 10, productName: "バードワイン", unitPrice: 210 }
]

document.addEventListener("DOMContentLoaded", function () {
    // データ配列に基づいてCollectionViewを作成します
    let view = new wijmo.collections.CollectionView(products);

    // unitPriceの降順にソートします
    let sortDesc = new wijmo.collections.SortDescription('unitPrice', false);
    view.sortDescriptions.push(sortDesc);

    // unitPriceが200より大きい項目だけを表示します
    view.filter = (item) => { return item.unitPrice > 200 };

    // ソートおよびフィルタ処理した結果をリストに追加します
    view.items.forEach((item) => {
        var newlist = document.createElement("li");
        var newtxt = document.createTextNode(item.productId + ': ' + item.productName + ' ' + item.unitPrice);
        newlist.appendChild(newtxt);
        document.getElementById("product_list").appendChild(newlist);
    });
});

以上設定は完了です。Visual Studio Code上で「index.html」を右クリックして、[Open with Live Server]を実行します。

Live Serverの実行

実行後、ブラウザ上にソート、フィルタされた結果のリストが表示されます。

ソート、フィルタされたリスト

FlexGridと一緒に使ってみよう!

CollectionViewはWijmoが提供する各種コントロールのデータソースとして直接設定することができます。ここからはデータグリッドコントロール「FlexGrid」と一緒に使う方法をご紹介します。FlexGridの基本的な使い方は以下をご覧ください。

参照の追加

FlexGridを使用するために、Wijmoのライブラリの参照を追加します。Wijmoのスタイル、FlexGridのモジュール、カルチャーのモジュールを追加し、bodyにはFlexGridを表示するコンテナ部分をdivタグで定義します。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>CollectionView入門</title>

    <!-- Wijmoのスタイル(必須) -->
    <link href="css/wijmo.min.css" rel="stylesheet" />

    <!-- Wijmoのコアモジュール(必須) -->
    <script src="scripts/wijmo.min.js"></script>
    <!-- FlexGridのモジュール(必須) -->
    <script src="scripts/wijmo.grid.min.js"></script>
    <!-- Wijmoカスタムカルチャー(オプション。任意のカルチャーを設定する) -->
    <script src="scripts/wijmo.culture.ja.min.js"></script>

    <script src="scripts/app.js"></script>
</head>
<body>
    <div id="Wijmo_FlexGrid" style="height: 600px;"></div>
</body>
</html>

ダミーの配列データを設定する

Web APIと連携する前に、記事の前半で使用したダミーの配列データを表示させてみます。以下のように「app.js」の中身を書き換え、CollectionViewをFlexGridのitemSourceプロパティに設定します。

・・・(中略)
document.addEventListener("DOMContentLoaded", function () {
    // データ配列に基づいてCollectionViewを作成します
    let view = new wijmo.collections.CollectionView(products);

    let flexGrid = new wijmo.grid.FlexGrid('#Wijmo_FlexGrid', {
        itemsSource: view,
    })
});

実行すると、先ほどのデータをFlexGrid上に表示できました。

CollectionViewからFlexGridにデータ表示

FlexGridにデータを表示する場合、過去の入門記事で紹介した方法のように、CollectionViewを作成せずに、itemSourceプロパティに直接配列データを設定する方法もあります。実はこの場合もFlexGridの内部では暗黙的にCollectionViewが設定される仕様となっています。

単純にデータを表示するだけなら上記のように暗黙的にCollectionViewを使う方法もありますが、明示的にCollectionViewを使うことによって、ユーザー操作を伴わないソートやフィルタ、後述する更新データの追跡などが可能になります。

以下はあらかじめソート、フィルタされたデータをFlexGridに表示する例です。

・・・(中略)
document.addEventListener("DOMContentLoaded", function () {
    // データ配列に基づいてCollectionViewを作成します
    let view = new wijmo.collections.CollectionView(products);

    // unitPriceの降順にソートします
    let sortDesc = new wijmo.collections.SortDescription('unitPrice', false);
    view.sortDescriptions.push(sortDesc);

    // unitPriceが200より大きい項目だけを表示します
    view.filter = (item) => { return item.unitPrice > 200 };

    let flexGrid = new wijmo.grid.FlexGrid('#Wijmo_FlexGrid', {
        itemsSource: view,
    })
});

実行すると、記事の前半でリストを表示したときと同様に、ソート、フィルタ済みのデータを表示できました。

ソート、フィルタ済みのデータを表示

Web APIと連携してみよう!

WijmoのようなJavaScriptライブラリを用いた開発を行う場合、表示するデータの取得にはWeb APIを使用するのが一般的です。WijmoではHTTPのリクエストに使用できる「httpRequestメソッド」も提供しているので、Web APIの呼び出しも簡単に実行できます。

Web APIから取得したレスポンス(JSONデータ)は、シリアライズしてCollectionViewに渡し、Wijmoの各種コントロールのデータソースに設定します。

Wijmoを使用したアプリケーション開発
Wijmoを使用したアプリケーション開発

今回は以下の記事で作成したASP.NET Core Web APIと連携を行いたいと思います。

ASP.NET Core Web API

データの表示(READ)

まずはWeb APIから取得したデータを、CollectionViewを介してFlexGridに表示します。httpRequestメソッドでWeb APIにGETリクエストを送信し、結果をシリアライズしてCollectionViewのsourceCollectionプロパティに設定します。

・・・(中略)
document.addEventListener("DOMContentLoaded", function () {
    let view = new wijmo.collections.CollectionView();
    // 実行するWeb APIのURLを設定します
    let url = 'https://localhost:44301/api/Products/';

    wijmo.httpRequest(url, {
        success: function (xhr) {
            view.sourceCollection = JSON.parse(xhr.response);
        }
    });

    let flexGrid = new wijmo.grid.FlexGrid('#Wijmo_FlexGrid', {
        itemsSource: view,
    })
});

実行すると、Web APIから取得したデータをFlexGrid上に表示できます。

Web APIから取得したデータを表示

CollectionViewで変更を追跡する

ここからは登録、更新、削除処理を実装していきますが、CollectionViewには、データの変更を追跡する機能があるので、このようなCRUD処理を行うアプリケーションを開発する際に非常に有用です。変更された内容はそれぞれ以下のコレクションに保存されます。

itemsAdded変更の追跡を有効化してから、コレクションに追加されたレコードを含む配列を取得します
itemsEdited変更の追跡を有効化してから、コレクションで編集されたレコードを含む配列を取得します
itemsRemoved変更の追跡を有効化してから、コレクションから削除されたレコードを含む配列を取得します

変更の追跡を有効にするにはCollectionViewの「trackChangesプロパティ」をtrueに設定します。また、グリッド上で新規登録、削除が実行できるように、FlexGridの「allowAddNewプロパティ」と「allowDeleteプロパティ」もtrueに設定します。

・・・(中略)
document.addEventListener("DOMContentLoaded", function () {
    let view = new wijmo.collections.CollectionView();
    // 実行するWeb APIのURLを設定します
    let url = 'https://localhost:44301/api/Products/';

    // 変更の追跡を有効化
    view.trackChanges = true;

    wijmo.httpRequest(url, {
        success: function (xhr) {
            view.sourceCollection = JSON.parse(xhr.response);
        }
    });

    let flexGrid = new wijmo.grid.FlexGrid('#Wijmo_FlexGrid', {
        itemsSource: view,
        allowAddNew: true,
        allowDelete: true
    })
});

さらに登録、更新、削除処理を実行するためのボタンを「index.html」に追加します。

・・・(中略)
<body>
    <button id="update">更新</button>
    <div id="Wijmo_FlexGrid" style="height: 600px;"></div>
</body>

データの登録(CREATE)

「app.js」に以下のコードを追加し、画面の[更新]ボタンをクリックしたときに、Web APIにPOSTリクエストを送信します。dataプロパティには、グリッドに追加された項目の配列が格納されている、CollectionViewのitemsAddedプロパティを設定します。

document.addEventListener("DOMContentLoaded", function () {
・・・(中略)
    document.getElementById('update').addEventListener('click', function () {
        //POST
        for (var i = 0; i < view.itemsAdded.length; i++) {
            wijmo.httpRequest(url, {
                method: 'POST',
                data: view.itemsAdded[i]
            });
        }
    });
});

データの更新(UPDATE)

「app.js」に以下のコードを追加し、画面の[更新]ボタンをクリックしたときに、Web APIにPUTリクエストを送信します。リクエストするURLとdataプロパティには、グリッド上で変更された項目の配列が格納されている、CollectionViewのitemsEditedプロパティから取得したproductId、および配列そのものをそれぞれ設定します。

document.addEventListener("DOMContentLoaded", function () {
・・・(中略)
    document.getElementById('update').addEventListener('click', function () {
    ・・・(中略)
        //PUT  
        for (var i = 0; i < view.itemsEdited.length; i++) {
            wijmo.httpRequest(url + view.itemsEdited[i].productId, {
                method: 'PUT',
                data: view.itemsEdited[i]
            });
        }
    });
});

データの削除(DELETE)

「app.js」に以下のコードを追加し、画面の[更新]ボタンをクリックしたときに、Web APIにDELETEリクエストを送信します。リクエストするURLには、グリッド上で削除された項目の配列が格納されている、CollectionViewのitemsRemovedプロパティから取得したproductIdを設定します。

document.addEventListener("DOMContentLoaded", function () {
・・・(中略)
    document.getElementById('update').addEventListener('click', function () {
    ・・・(中略)
        //DELETE
        for (var i = 0; i < view.itemsRemoved.length; i++) {
            wijmo.httpRequest(url + view.itemsRemoved[i].productId, {
                method: 'DELETE'
            });
        }
    });
});

さいごに

今回はWijmoのデータ管理クラス「CollectionView」の基本的な用法をご紹介しました。ソートやフィルタといった機能のほか、業務アプリケーションに必須のCRUD処理の実装に必要なデータの変更の追跡まで簡単に実現できるので、Wijmoでの開発の際には是非ご利用検討いただければと思います。

弊社Webサイトでは、Wijmoの機能を手軽に体験できるデモアプリケーションやトライアル版も公開しておりますので、こちらもご確認ください。

また、ご導入前の製品に関するご相談、ご導入後の各種サービスに関するご質問など、お気軽にお問合せください。