ウィジェットでデータ ソースを使用

出典:ArcGIS Experience Builder - Guide - Use data source in widget

データ ソースは、ウィジェットがデータにアクセスする方法を定義します。データ ソースを使用して行いたいことは様々ですが、それぞれについて紹介します。

  • ウィジェットの設定でデータ ソースを選択
  • ウィジェット ランタイムのデータを読み込んで表示
  • ユーザー入力に基づくデータのフィルタリングやクエリー
  • データ上の選択を処理
  • ArcGIS Maps SDK for JavaScript のフィーチャ オブジェクトとデータ ソースの同期
  • ウィジェットで出力データ ソースの生成
  • ウィジェットでメッセージの公開

本ドキュメントで使用している appConfig という変数は、アプリの config JSON オブジェクトを指します。ArcGIS Online または Enterprise 版では、アプリの config JSON はアイテム データとして保存され、Developer Edition では server/public/apps/[appId]/config.json (公開版) または server/public/apps/[appId]/resources/config.json (ドラフト版) の下に保存されます。

ウィジェットの設定でデータ ソースを選択

ウィジェットの設定でデータ ソースを選択するには、DataSourceSelector コンポーネントを使用する必要があります。Experience Builder は、複数の種類のデータ ソースをサポートしています。

DataSourceSelector コンポーネントを使用するには、ウィジェットが対応するデータ ソースの種類を types プロパティで設定する必要があります。jimu-coreAllDataSourceTypes がサポートされているデータ ソース タイプです。データ ソースを選択した後は、onChange コールバックを通じて選択されたデータ ソースを取得できます。onChange の中では、props.onSettingChange() を呼び出して、選択されたソースを appConfig に保存します(appConfig.widgets[widgetId].useDataSources)。ユーザーが新しいデータ ソースを追加した場合、そのデータ ソースは appConfig.dataSources に保存されます。詳しくはサンプル ウィジェットをご覧ください。

<DataSourceSelector
   types={Immutable([AllDataSourceTypes.FeatureLayer])}
   useDataSources={props.useDataSources}
   useDataSourcesEnabled={props.useDataSourcesEnabled}
   onToggleUseDataEnabled={onToggleUseDataEnabled}
   onChange={onDataSourceChange}
   widgetId={props.id}
/>

データ ソースを選択した後、ユーザーがデータからフィールドを選択できるようにしたい場合があります。そのためには、FieldSelector コンポーネントを使用します。データ ソースと同様に、appConfig.widgets[widgetId].useDataSources にも選択したフィールドを保存する必要があります。データ ソースはこれらのフィールドを自動的に読み込みますが、パフォーマンスの観点から、使用されていないフィールドは読み込まれません。

{
   props.useDataSources && props.useDataSources.length > 0 &&
   <FieldSelector
      useDataSources={props.useDataSources}
      onChange={onFieldChange}
      selectedFields={props.useDataSources[0].fields || Immutable([])}
   />
}

ウィジェット ランタイムのデータを読み込んで表示

ウィジェット設定でデータ ソースを選択すると、ウィジェット ランタイムは props.useDataSources で選択したデータ ソースを取得することができます。データを読み込むには、DataSource インスタンスを使用します。DataSource インスタンスを取得するには、DataSourceManager または DataSourceComponent を使用します。DataSourceComponent を使用する場合は、useDataSource プロパティを渡します。DataSource インスタンスを取得するには、onDataSourceCreated コールバックを使用します。

データを読み込むには、render 関数を使用してデータを表示します。こちらのサンプルウィジェットを参照してください。別の方法として、onDataSourceInfoChange コールバックを使用し、データ ソースの現在のデータに応じてこのコールバック関数でウィジェットの UI を更新することができます。ウィジェットがデータをロードする必要がある場合、querywidgetId プロパティを渡します。フレームワークは、複数のウィジェットが同じデータ ソースに適用するクエリパラメータを管理するのにこのプロパティを使用するため、widgetId は必須です。

データをロードしたいが、データ ソースのデータを変更したくない場合は、localId プロパティを渡します。これにより、ローカルデータ ソースが作成され、使用することができます。推奨される localId のパターンは、例えば、widget_1_my_local のように widgetId + ??? とします。

DataSourceComponent をレンダリングすると、データ ソースのインスタンスが作成されますが、データは初期状態ではロードされません。なぜなら、query プロパティを渡すことを期待しているので、別のネットワーク要求が発生するためです。読み込まれたデータを取得するには、dataSource.getRecords() を使用します。データはページングされ、デフォルトのページングサイズは 100 です。ユーザーはビルダーデータ設定パネルでページングサイズを変更することができます。ロードされたデータはクライアント上にキャッシュされ、クエリ条件が変更されるとキャッシュはクリアされます。

データを表示する際、表示されるページサイズはクエリのページサイズと同じである必要はありません。例えば、クエリのページサイズが 100 の場合、dataSource.getRecordsByPage(1, 10) を使用して、最初の 10 レコードを取得して表示することが可能です。

レコードの総数を取得するには、queryCount プロパティを渡し、dataSource.count で件数を取得します。

データ ソース情報が変更されるたびに、データレンダリング関数とonDataSourceInfoChange コールバックが呼び出されます。情報の内容は以下の通りです。

  • instanceStatus: データ ソースのインスタンスが正常に作成されたかどうか
  • status: データがロード中か、ロードされたか
  • countStatus: データのカウントがロード中か、ロードされたか
  • selectedIds: 選択されたデータ ID
  • selectOptions: クエリ (フィルター) でデータを選択すると、データ ソースはクエリを実行し、その結果を selectedIds に格納する
  • widgetQueries: データ ソースに適用されるクエリ (フィルター) ウィジェット
  • version: バージョン番号は、クライアント側でデータの変更を管理するために使用されます。そのため、データ ソース利用者はデータが変更されたことを認識することができます。
  • gdbVersion: ブランチ バージョニングをサポートするフィーチャ サービスのためのもの。ブランチ バージョン管理ウィジェットでブランチ バージョンが切り替わると、そのバージョンがここに保存されます。

多くの場合、ウィジェットは現在のデータ ソース情報と以前の情報とを比較して、何を更新する必要があるかを判断する必要があります。

ウィジェットがデータ ソースの情報変更を聞く必要があるが、データ ソースのデータレコードを使う必要がない場合、query パラメータを省略し、onQueryRequired コールバックでクエリを実行することが可能です。

データ ソースのフィールドを取得するには、dataSource.getSchema().fields を使用します。

ユーザー入力に基づくデータのフィルタリングやクエリー

ウィジェットがデータをフィルタリングすると、データ ソース インスタンスのデータが変更され、すべてのウィジェットがその変更を観察します。ウィジェットがデータ ソースを介してデータをクエリーする場合、データ ソース インスタンスのデータは影響を受けません。

複数のウィジェットが同じデータ ソースにフィルターを適用する場合、属性フィルターは and 演算子で結びつけられます。ジオメトリ フィルターの場合、最後にジオメトリ フィルターを適用したウィジェット (アプリ設定でのウィジェット追加順) からのフィルターが使用されます。

  • データ ソースにフィルターをかけるには、データ ソースの設定により、基本的に 2 つの方法があります。

    • ウィジェットでデータを読み込む場合は、以下のようにDataSourceComponent を使うのがおすすめです。
    <DataSourceComponent useDataSource={} widgetId={} query={}>
    { Your render method }
    </DataSourceComponent>
    

    DataSourceComponent の使用例は、Message subscriber のサンプルServer-side output data source のサンプルに記載されています。

    dataSource.load() を使用して、データの読み込みとフィルタリングも可能です。

    • ウィジェットがデータを読み込まない場合は、Data SourceupdateQueryParams() 関数を使用することができます。例として、Filter feature layer のサンプルをご覧ください。
  • データ ソースからデータをクエリーするには、dataSource.query() を使用します。データをクエリーする際には、このデータ ソースに適用されているフィルターも使用されます。

データ上の選択を処理

Experience Builder アプリにおける選択動作の設計は、すべてのウィジェットが同じ選択を更新、監視することを前提としています。例えば、ユーザーがリスト ウィジェット内でレコードを選択すると、テキスト ウィジェットも選択ビューを使用していればその選択を認識できます。すべてのデータ ソースには、選択データ ビューがあり、選択を管理します。さらに、選択されたレコード ID は Redux のアプリ ストアに保存されるため、同じデータ ソースを使用する他のウィジェットは選択の変更を検知できます。

データ ソース内のデータ レコードを選択するには、dataSource.selectRecordById()dataSource.selectRecordsByIds()、または dataSource.selectRecords() を使用できます。dataSource.selectRecordById()dataSource.selectRecordsByIds() を使用する場合、レコードがすでにデータ ソースに読み込まれていれば、第 2 引数は不要です。読み込まれていない場合は、第 2 引数にレコード情報を渡す必要があります。これにより、他のウィジェットも選択されたレコードを読み取れるようになります。dataSource.selectRecords() はクエリー パラメーターを使ってレコードを選択できます。この場合、クエリー結果はデータソース情報に設定され、他のウィジェットもそれに応じて更新されます。

選択されたレコードを読み取るには、dataSource.getSelectedRecords() を使用します。

WebMap/WebScene の使用

ArcGIS Maps SDK for JavaScript の WebMap と WebScene は、データ ソースとして jimu-arcgis パッケージでラッピングされています。WebMap にアクセスする場合は WebMapDataSource を、WebScene にアクセスする場合は WebSceneDataSource を使用します。これらのデータ ソースの使用方法については、MapView のサンプルをご覧ください。WebMap と WebScene オブジェクトに加えて、これらのオブジェクト内のすべてのレイヤーはデータ ソースとしてラッピングされているため、getChildDataSources() を呼び出してすべてのレイヤー データ ソースを取得できます。サポートされるレイヤーとサービスは、SupportedLayerServiceTypesSupportedServiceTypes で定義されています。ArcGIS Maps SDK for JavaScript のlayerがあり、関連するレイヤーのデータ ソースを検索したい場合は、mapDs.getDataSourceByLayer() または mapDs.createDataSourceByLayer() を実行します。DataSourceComponent または DataSourceManager でマップ データ ソース (WebMapDataSource または WebSceneDataSource) を作成した場合、アプリの起動後、その子データ ソースは自動的に作成されないことに注意してください。すべての子データ ソースを作成するには、await mapDs.childDataSourcesReady() を実行します。

FeatureLayer の使用

ワークフローによっては、フィーチャ レイヤーで直接動作する軽量なエクスペリエンスを作成する必要があります。このシナリオでは、FeatureLayerDataSource クラスを使用します。一般的に、スタンドアロン レイヤーを使用するウィジェットは、layer プロパティを持たない FeatureLayerDataSource オブジェクトを取得しますが、Web マップまたは Web シーンからのフィーチャ レイヤーを使用すると、layer プロパティを持つ FeatureLayerDataSource オブジェクトを返します。Layer オブジェクトは ArcGIS Maps SDK for JavaScript から提供されています。ポップアップ情報を取得するには featureLayerDs.getPopupInfo() を、ID フィールドを取得するには featureLayerDs.getIdField() を、ジオメトリ タイプを取得するには featureLayerDs.getGeometryType() を使用します。

 const getLayerObject = (ds: FeatureLayerDataSource) => {
    return ds.layer; // null に設定することも可能です
 }

ウィジェット間のデータ共有

ウィジェットは、多くの場合、同じデータを共有します。この良い例が、エクスペリエンスでマップ ウィジェットとリスト ウィジェットを使用する場合です。リスト ウィジェットでフィーチャを選択すると、対応するフィーチャがマップ上で選択されます。これを実現する最も簡単な方法は、両方のウィジェットに同じデータ ソースを使用することです。たとえば、リスト ウィジェットでアイテムが選択されると、ウィジェットは datasource.selectRecordById() を呼び出して、app store のデータ ソースの状態を更新します。これにより、マップ ウィジェットでは、現在選択されているアイテムを適宜レンダリングすることができます。また、現在選択されているアイテムの ID が URL に配置されるため、現在のアプリの状態を他の人と共有することが可能になります。

ArcGIS Maps SDK for JavaScript のフィーチャ オブジェクトとデータ ソースの同期

Experience Builder ウィジェットでは、ArcGIS Maps SDK for JavaScript を使用してフィーチャを取得することができます。その後、他のウィジェットがこれらのフィーチャを使用できるようにしたい場合があります。たとえば、マップ上でこれらのフィーチャをハイライト表示したり、リスト ウィジェットでこれらのフィーチャを表示したりする必要があるかもしれません。これには、以下の 3 つのオプションがあります。

  1. データ ソースでこれらのフィーチャ レコードを選択する
    • 使用できるデータ ソース インスタンスがあれば、dataSource.selectRecordsByIds() を呼んでこれらのレコードを選択することができます。Graphic インスタンスを取得する場合は、まず FeatureRecord インスタンスを作成する (featureLayerDataSource.buildRecord(graphic)) 必要があります。
  2. ウィジェットから出力データ ソースを生成する
  3. メッセージを公開する
    • ウィジェットが何らかのフィーチャを生成する場合、DataRecordSetChangeMessage メッセージを公開することで、他のウィジェットがサブスクライブできるようになります。

MapView/SceneView または LayerView での作業

ウィジェットがデータ ソースと連動する場合、MapView/SceneView とも連動する必要がある場合が多くあります。ウィジェットが JimuMapViewComponent によってJimuMapView インスタンスを取得した後、jimuMapView.dataSourceId によって MapView/SceneView の対応するデータ ソースを取得し、jimuMapView.jimuLayerViews によって関連レイヤーを取得することができます。jimuLayerView インスタンスを介して、jimuMapView.dataSource によって、レイヤー ビューの対応するデータ ソースを取得することもできます。一般に、レイヤーからデータ ソースと同期する機能を取得するには、以下のオプションがあります。

  • フィーチャの ID フィールドを使用して、データ ソースから関連するデータ レコードを検索
  • FeatureDataRecord インスタンスを作成し、そのフィーチャに対応するデータ レコードを作成
  • FeatureDataRecord のインスタンスから、featureDataRecord.getFeature() でフィーチャを取得