Hierarchical Grid ロードオンデマンド
Ignite UI for Web Components IgcHierarchicalGridComponent は、要求するサーバーからのデータを最低限にすることによりすばやく描画できます。このため、ユーザーがビューで結果を確認でき、表示データをインタラクティブに操作できます。初期時にグリッドのデータのみが取得されて描画され、ユーザーが子グリッドを含む行を拡張した後のみ、特定の子グリッドのデータを取得します。このメカニズムは、ロードオンデマンドであらゆるリモートデータとの設定が簡単にできます。
このトピックは、既に利用可能なリモート サービスと通信してリモート サービス プロバイダーを作成し、ロードオンデマンドを設定する方法を説明します。以下は、デモと作成手順を示します。
Web Components Hierarchical Grid ロードオンデマンドの例
リモート サービス プロバイダー
はじめにサービス プロバイダーを準備して階層グリッドに必要なデータを取得します。
基本データの取得
ブラウザーが提供する fetch() グローバル関数を使用した HTTP プロトコルでバックエンドサービスと通信します。データを取得にはサービスのシンプルなメソッドが必要となります。
export async function getData(dataState: any): Promise<any> {
const response = await fetch(buildUrl(dataState));
const data = await response.json();
return data;
}
buildUrl() は取得したデータに基づいて url を生成するメソッドになります。実行された非同期のため、Promise を返します。それにより後でサブスクライブし、アプリケーションで処理を進めてグリッドへ渡すことができます。
要求 URL のビルド
次に GET 要求の URL をビルドする方法を定義します。メイン グリッドのデータを取得できますが含まれる子グリッドのデータも取得できます。ルート レベルにこちらの Customers データを使用し、それ以外のレベルには Orders と Details を使用します。このモデルはアプリケーションごとに異なりますが、ここでは以下を使用します。
はじめに必要となるのはグリッドのデータ、親業のプライマリキーとその一意の ID をどこから取得するかを決定するテーブルの key が必要です。
これらすべてを dataState オブジェクトで定義します。例:
const dataState: {
key: string;
parentID: any;
parentKey: string;
rootLevel: boolean;
} = {
//...
};
function buildUrl(dataState: any) {
let qS = "";
if (dataState) {
if (dataState.rootLevel) {
qS += `${dataState.key}`;
} else {
qS += `${dataState.parentKey}/${dataState.parentID}/${dataState.key}`;
}
}
return `${URL}${qS}`;
}
結果
最後に、リモート サービスは以下のようになります。
const URL = `https://data-northwind.indigo.design/`;
export async function getData(dataState: any): Promise<any> {
const response = await fetch(buildUrl(dataState));
const data = await response.json();
return data;
}
function buildUrl(dataState: any) {
let qS = "";
if (dataState) {
if (dataState.rootLevel) {
qS += `${dataState.key}`;
} else {
qS += `${dataState.parentKey}/${dataState.parentID}/${dataState.key}`;
}
}
return `${URL}${qS}`;
}
階層グリッドの`設定
次に階層グリッドを設定してリモート サービス プロバイダーに接続します。
テンプレートの地祇
最初に階層グリッド テンプレートを必要な階層レベルで定義します。customers のルート グリッド primaryKey は最初のレベルの orders の customerId です。orderId と各 order 詳細の productId です。各データベース テーブルとキーで初期テンプレートを定義します。
<igc-hierarchical-grid id="hGrid" primary-key="customerId" height="600px">
<igc-column field="customerId" hidden="true"></igc-column>
<igc-column field="companyName" header="Company Name"></igc-column>
<igc-column field="contactName" header="Contact Name"></igc-column>
<igc-column field="contactTitle" header="Contact Title"></igc-column>
<igc-column field="address.country" header="Country"></igc-column>
<igc-column field="address.phone" header="Phone"></igc-column>
<igc-row-island child-data-key="Orders" primary-key="orderId">
<igc-column field="orderId" hidden="true"></igc-column>
<igc-column field="shipAddress.country" header="Ship Country"></igc-column>
<igc-column field="shipAddress.city" header="Ship City"></igc-column>
<igc-column field="shipAddress.street" header="Ship Address"></igc-column>
<igc-column field="orderDate" header="Order Date" data-type="date"></igc-column>
<igc-row-island child-data-key="Details" primary-key="productId">
<igc-column field="productId" hidden="true"></igc-column>
<igc-column field="quantity" header="Quantity"></igc-column>
<igc-column field="unitPrice" header="Unit Price"></igc-column>
<igc-column field="discount" header="Discount"></igc-column>
</igc-row-island>
</igc-row-island>
</igc-hierarchical-grid>
ルート レベル階層グリッドと最終的にはその子のデータがテンプレートに必要となります。
id="hGrid" 参照が使用できるため、コードでサービスからデータ取得後にルート グリッドのデータを簡単に設定できます。
展開されている子にデータを設定する方法は異なります。行がはじめて展開されたときに新し子 IgcHierarchicalGridComponent が描画がされるため、データを設定するために新しく作成されたグリッドの参照を取得する必要があります。各 IgcRowIslandComponent コンポーネントに GridCreated イベントがあり、特定の子アイランドに新しい子グリッドが作成されたときに発生します。新しいグリッドの参照を取得するために使用でき、サービスからデータを要求して適用します。
サービスをビルドしているためルートレベルの場合に情報のみが必要なため、すべてのアイランドに 1 メソッドを使用できます。このすべての情報には、イベント引数から直接またはイベントをトリガーする行アイランドからアクセスできます。
gridCreated を使用するメソッドに名前を付けます。
GridCreated イベントは parentID プロパティ、owner として行アイランドへの参照、新しい子 grid プロパティを提供するため、最初の引数として渡されます。親行の primaryKey についての情報はありませんが、バインドした行アイランドに基づいて 2 番目の引数として簡単に渡すことができます。
変更を加えたテンプレート ファイルは以下のようになります。
<igc-hierarchical-grid id="hGrid" primary-key="customerId" height="600px">
<igc-column field="customerId" hidden="true"></igc-column>
<igc-column field="companyName" header="Company Name"></igc-column>
<igc-column field="contactName" header="Contact Name"></igc-column>
<igc-column field="contactTitle" header="Contact Title"></igc-column>
<igc-column field="address.country" header="Country"></igc-column>
<igc-column field="address.phone" header="Phone"></igc-column>
<igc-row-island id="ordersRowIsland" child-data-key="Orders" primary-key="orderId">
<igc-column field="orderId" hidden="true"></igc-column>
<igc-column field="shipAddress.country" header="Ship Country"></igc-column>
<igc-column field="shipAddress.city" header="Ship City"></igc-column>
<igc-column field="shipAddress.street" header="Ship Address"></igc-column>
<igc-column field="orderDate" header="Order Date" data-type="date"></igc-column>
<igc-row-island id="orderDetailsRowIsland" child-data-key="Details" primary-key="productId">
<igc-column field="productId" hidden="true"></igc-column>
<igc-column field="quantity" header="Quantity"></igc-column>
<igc-column field="unitPrice" header="Unit Price"></igc-column>
<igc-column field="discount" header="Discount"></igc-column>
</igc-row-island>
</igc-row-island>
</igc-hierarchical-grid>
constructor() {
const ordersRowIsland = document.getElementById("ordersRowIsland");
const orderDetailsRowIsland = document.getElementById("orderDetailsRowIsland");
ordersRowIsland.addEventListener("gridCreated", (event: any) => {
this.gridCreated(event, "Customers");
});
orderDetailsRowIsland.addEventListener("gridCreated", (event: any) => {
this.gridCreated(event, "Orders");
});
}
サービスへ接続
最後の手順の 1 つとして、以前作成したサービスに階層グリッドを接続することです。
ルート グリッドへの参照を取得して、そのデータを設定します。親がないため、rootLevel は true でそのキーのみをサービスの getData へ渡すことができます。サブスクライブする必要のある Promise を返します。
constructor() {
const hierarchicalGrid = document.getElementById("hGrid") as IgcHierarchicalGridComponent;
getData({ parentID: null, rootLevel: true, key: "Customers" }).then((data: any) => {
hierarchicalGrid.data = data;
hierarchicalGrid.markForCheck();
});
}
次に作成した新しい子グリッドのデータを要求する gridCreated メソッドを作成する必要があります。
ルート レベル グリッド データの取得と同様に、ここではparentID や parentKey などの情報を渡す必要があります。rootLevel はいずれの子も false です。
public gridCreated(event: CustomEvent<IgcGridCreatedEventArgs>, _parentKey: string) {
const context = event.detail;
const dataState = {
key: context.owner.childDataKey,
parentID: context.parentID,
parentKey: _parentKey,
rootLevel: false
};
getData(dataState).then((data: any[]) => {
context.grid.data = data;
context.grid.markForCheck();
});
}
これにより、アプリケーションの設定はほぼ完了です。最後の手順は、空グリッドを表示する代わりにユーザーにデータがまだ読み込み中であることを通知してユーザー エクスペリエンスを向上します。IgcHierarchicalGridComponent は、グリッドが空のときに表示できるインジケーターの読み込みサポートします。新しいデータが取得されると読み込みインジケーターが非表示となりデータが描画されます。
読み込み通知の設定
IgcHierarchicalGridComponent は、isLoading プロパティを true に設定して読み込みインジケーターを表示できます。データが読み込まれるまでルートグリッドにあらかじめ設定しますが、新しい子グリッドを作成する際にも必要です。テンプレートで常に true に設定できますが、false に設定してサービスが空配列を返した場合は非表示にしてデータのないグリッドを表示できます。
以下は構成の最終バージョンです。
constructor() {
const hierarchicalGrid = document.getElementById("hGrid") as IgcHierarchicalGridComponent;
const ordersRowIsland = document.getElementById("ordersRowIsland");
const orderDetailsRowIsland = document.getElementById("orderDetailsRowIsland");
ordersRowIsland.addEventListener("gridCreated", (event: any) => {
this.gridCreated(event, "Customers");
});
orderDetailsRowIsland.addEventListener("gridCreated", (event: any) => {
this.gridCreated(event, "Orders");
});
hierarchicalGrid.isLoading = true;
getData({ parentID: null, rootLevel: true, key: "Customers" }).then((data: any) => {
hierarchicalGrid.isLoading = false;
hierarchicalGrid.data = data;
hierarchicalGrid.markForCheck();
});
}
public gridCreated(event: CustomEvent<IgcGridCreatedEventArgs>, _parentKey: string) {
const context = event.detail;
const dataState = {
key: context.owner.childDataKey,
parentID: context.parentID,
parentKey: _parentKey,
rootLevel: false
};
context.grid.isLoading = true;
getData(dataState).then((data: any[]) => {
context.grid.isLoading = false;
context.grid.data = data;
context.grid.markForCheck();
});
}
API リファレンス
その他のリソース
コミュニティに参加して新しいアイデアをご提案ください。