Hierarchical Grid ロードオンデマンド

    Ignite UI for React IgrHierarchicalGrid は、要求するサーバーからのデータを最低限にすることによりすばやく描画できます。このため、ユーザーがビューで結果を確認でき、表示データをインタラクティブに操作できます。初期時にグリッドのデータのみが取得されて描画され、ユーザーが子グリッドを含む行を拡張した後のみ、特定の子グリッドのデータを取得します。このメカニズムは、ロードオンデマンドであらゆるリモートデータとの設定が簡単にできます。

    このトピックは、既に利用可能なリモート サービスと通信してリモート サービス プロバイダーを作成し、ロードオンデマンドを設定する方法を説明します。以下は、デモと作成手順を示します。

    React Hierarchical Grid ロードオンデマンドの例

    リモート サービス プロバイダー

    はじめにサービス プロバイダーを準備して階層グリッドに必要なデータを取得します。

    基本データの取得

    ブラウザーが提供する fetch() グローバル関数を使用した HTTP プロトコルでバックエンドサービスと通信します。データを取得にはサービスのシンプルなメソッドが必要となります。

    export function getData(dataState: any): any {
        return fetch(buildUrl(dataState))
            .then((result) => result.json());
    }
    

    buildUrl() は取得したデータに基づいて url を生成するメソッドになります。実行された非同期のため、Promise を返します。それにより後でサブスクライブし、アプリケーションで処理を進めてグリッドへ渡すことができます。

    要求 URL のビルド

    次に GET 要求の URL をビルドする方法を定義します。メイン グリッドのデータを取得できますが含まれる子グリッドのデータも取得できます。ルート レベルにこちらCustomers データを使用し、それ以外のレベルには OrdersDetails を使用します。このモデルはアプリケーションごとに異なりますが、ここでは以下を使用します。

    はじめに必要となるのはグリッドのデータ、親業のプライマリキーとその一意の 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 function getData(dataState: any): any {
        return fetch(buildUrl(dataState))
            .then((result) => result.json());
    }
    
    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 です。各データベース テーブルとキーで初期テンプレートを定義します。

    <IgrHierarchicalGrid ref={hierarchicalGrid} primaryKey="customerId" height="600px">
        <IgrColumn field="customerId" hidden={true}></IgrColumn>
        <IgrColumn field="companyName" header="Company Name"></IgrColumn>
        <IgrColumn field="contactName" header="Contact Name"></IgrColumn>
        <IgrColumn field="contactTitle" header="Contact Title"></IgrColumn>
        <IgrColumn field="address.country" header="Country"></IgrColumn>
        <IgrColumn field="address.phone" header="Phone"></IgrColumn>
        <IgrRowIsland childDataKey="Orders" primaryKey="orderId">
            <IgrColumn field="orderId" hidden={true}></IgrColumn>
            <IgrColumn field="shipAddress.country" header="Ship Country"></IgrColumn>
            <IgrColumn field="shipAddress.city" header="Ship City"></IgrColumn>
            <IgrColumn field="shipAddress.street" header="Ship Address"></IgrColumn>
            <IgrColumn field="orderDate" header="Order Date" dataType="date"></IgrColumn>
            <IgrRowIsland childDataKey="Details" primaryKey="productId">
                <IgrColumn field="productId" hidden={true}></IgrColumn>
                <IgrColumn field="quantity" header="Quantity"></IgrColumn>
                <IgrColumn field="unitPrice" header="Unit Price"></IgrColumn>
                <IgrColumn field="discount" header="Discount"></IgrColumn>
            </IgrRowIsland>
        </IgrRowIsland>
    </IgrHierarchicalGrid>
    

    ルート レベル階層グリッドと最終的にはその子のデータがテンプレートに必要となります。

    ref={hierarchicalGrid} 参照が使用できるため、コードでサービスからデータ取得後にルート グリッドのデータを簡単に設定できます。

    展開されている子にデータを設定する方法は異なります。行がはじめて展開されたときに新し子 IgrHierarchicalGrid が描画がされるため、データを設定するために新しく作成されたグリッドの参照を取得する必要があります。各 IgrRowIsland コンポーネントに GridCreated イベントがあり、特定の子アイランドに新しい子グリッドが作成されたときに発生します。新しいグリッドの参照を取得するために使用でき、サービスからデータを要求して適用します。

    サービスをビルドしているためルートレベルの場合に情報のみが必要なため、すべてのアイランドに 1 メソッドを使用できます。このすべての情報には、イベント引数から直接またはイベントをトリガーする行アイランドからアクセスできます。

    gridCreated を使用するメソッドに名前を付けます。

    GridCreated イベントは行アイランド、parentID プロパティ、および新しい子グリッド プロパティへの参照を提供するため、これは最初と 2 番目の引数として渡されます。親行の primaryKey についての情報はありませんが、バインドした行アイランドに基づいて 2 番目の引数として簡単に渡すことができます。

    変更を加えたテンプレート ファイルは以下のようになります。

    <IgrHierarchicalGrid ref={hierarchicalGrid} primaryKey="customerId" height="600px">
        <IgrColumn field="customerId" hidden={true}></IgrColumn>
        <IgrColumn field="companyName" header="Company Name"></IgrColumn>
        <IgrColumn field="contactName" header="Contact Name"></IgrColumn>
        <IgrColumn field="contactTitle" header="Contact Title"></IgrColumn>
        <IgrColumn field="address.country" header="Country"></IgrColumn>
        <IgrColumn field="address.phone" header="Phone"></IgrColumn>
        <IgrRowIsland
          childDataKey="Orders"
          primaryKey="orderId"
          gridCreated={(
            rowIsland: IgrRowIsland,
            e: IgrGridCreatedEventArgs
          ) => gridCreated(rowIsland, e, "Customers")}
        >
            <IgrColumn field="orderId" hidden={true}></IgrColumn>
            <IgrColumn field="shipAddress.country" header="Ship Country"></IgrColumn>
            <IgrColumn field="shipAddress.city" header="Ship City"></IgrColumn>
            <IgrColumn field="shipAddress.street" header="Ship Address"></IgrColumn>
            <IgrColumn field="orderDate" header="Order Date" dataType="date"></IgrColumn>
            <IgrRowIsland
              childDataKey="Details"
              primaryKey="productId"
              gridCreated={(
                rowIsland: IgrRowIsland,
                e: IgrGridCreatedEventArgs
              ) => gridCreated(rowIsland, e, "Orders")}
            >
                <IgrColumn field="productId" hidden={true}></IgrColumn>
                <IgrColumn field="quantity" header="Quantity"></IgrColumn>
                <IgrColumn field="unitPrice" header="Unit Price"></IgrColumn>
                <IgrColumn field="discount" header="Discount"></IgrColumn>
            </IgrRowIsland>
        </IgrRowIsland>
    </IgrHierarchicalGrid>
    

    サービスへ接続

    最後の手順の 1 つとして、以前作成したサービスに階層グリッドを接続することです。

    useRef React フックを介してルート グリッドへの参照を取得し、そのデータを設定します。

    const hierarchicalGrid = useRef<IgrHierarchicalGrid>(null);
    

    グリッドがサービスのデータを要求して割り当てる前に描画されることを確認するために、useEffect React フックを使用します。親がないため、rootLeveltrue でそのキーのみをサービスの getData へ渡すことができます。サブスクライブする必要のある Promise を返します。

    useEffect(() => {
        getData({ parentID: null, rootLevel: true, key: "Customers" }).then(
          (data: any) => {
            hierarchicalGrid.current.data = data;
            hierarchicalGrid.current.markForCheck();
          }
        );
    }, []);
    

    次に作成した新しい子グリッドのデータを要求する gridCreated メソッドを作成する必要があります。

    ルート レベル グリッド データの取得と同様に、ここではparentIDparentKey などの情報を渡す必要があります。rootLevel はいずれの子も false です。

    function gridCreated(rowIsland: IgrRowIsland, event: IgrGridCreatedEventArgs, _parentKey: string) {
        const context = event.detail;
        const dataState = {
            key: rowIsland.childDataKey,
            parentID: context.parentID,
            parentKey: _parentKey,
            rootLevel: false,
        };
    
        getData(dataState).then((data: any[]) => {
            context.grid.data = data;
            context.grid.markForCheck();
        });
    }
    

    これにより、アプリケーションの設定はほぼ完了です。最後の手順は、空グリッドを表示する代わりにユーザーにデータがまだ読み込み中であることを通知してユーザー エクスペリエンスを向上します。IgrHierarchicalGrid は、グリッドが空のときに表示できるインジケーターの読み込みサポートします。新しいデータが取得されると読み込みインジケーターが非表示となりデータが描画されます。

    読み込み通知の設定

    IgrHierarchicalGrid は、IsLoading プロパティを true に設定して読み込みインジケーターを表示できます。データが読み込まれるまでルートグリッドにあらかじめ設定しますが、新しい子グリッドを作成する際にも必要です。テンプレートで常に true に設定できますが、false に設定してサービスが空配列を返した場合は非表示にしてデータのないグリッドを表示できます。

    以下は構成の最終バージョンです。

    const hierarchicalGrid = useRef<IgrHierarchicalGrid>(null);
    
    useEffect(() => {
        hierarchicalGrid.current.isLoading = true;
        
        getData({ parentID: null, rootLevel: true, key: "Customers" }).then(
          (data: any) => {
            hierarchicalGrid.current.isLoading = false;
            hierarchicalGrid.current.data = data;
            hierarchicalGrid.current.markForCheck();
        }
      );
    }, []);
    
    function gridCreated(rowIsland: IgrRowIsland, event: IgrGridCreatedEventArgs, _parentKey: string) {
        const context = event.detail;
        const dataState = {
            key: rowIsland.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 リファレンス

    その他のリソース

    コミュニティに参加して新しいアイデアをご提案ください。