Data sources define how your widget accesses data. There are a variety of things you may want to do with data sources, each of which are detailed below.
- Select a data source and save the used fields in the widget settings
- Read and display the data in the widget runtime
- Filter or query data based on user input
- Handle selection on data
- Sync the data source with the ArcGIS Maps SDK for JavaScript feature object
- Your widget may need to generate an output data source
- Your widget may need to publish a message
Note: when you see the app
variable used in this guide, it refers to the app config JSON object. For ArcGIS Online or Enterprise edition, the app config JSON is saved as item data; For developer edition, it is saved under server/public/apps/[app
(published version) or server/public/apps/[app
(draft version).
Select a data source in the widget settings
To select a data source in the widget settings, you should use the Data
component.
Experience Builder supports multiple types of data sources.
To use the Data
component, you must set the data source types that the widget supports through the types
prop. AllDataSourceTypes from jimu-core
is the supported data source types. After you select a data source, you can get the selected data sources through the on
callback. In the on
callback, you need to call props.on
to save the selected data sources into the app
(app
).
If the user adds a new data source, the newly-added data source is saved in app
. See this sample widget.
<DataSourceSelector
types={Immutable([AllDataSourceTypes.FeatureLayer])}
useDataSources={props.useDataSources}
useDataSourcesEnabled={props.useDataSourcesEnabled}
onToggleUseDataEnabled={onToggleUseDataEnabled}
onChange={onDataSourceChange}
widgetId={props.id}
/>
After selecting a data source, you may want to allow the user to select fields from the data. To do this, you can use the FieldSelector component.
Like the data source, you should save the selected fields in app
as well. The data source will automatically load these fields. For performance reasons, the fields that are not used won't be loaded.
{
props.useDataSources && props.useDataSources.length > 0 &&
<FieldSelector
useDataSources={props.useDataSources}
onChange={onFieldChange}
selectedFields={props.useDataSources[0].fields || Immutable([])}
/>
}
Read and display the data in the widget runtime
After a data source is selected in the widget settings, the widget runtime can get the selected data sources through props.use
. To read the data, use the Data
instance. To get the Data
instance, use Data
or Data
. To use Data
, pass the use
prop. To get the Data
instance, use the on
callback.
To read data, use the render function to display the data. See this sample widget. As an alternative, you can use the on
callback and update your widget UI in this callback function according to the current data in the data source.
If your widget needs to listen to the data source filter change, you can use on
callback to update the data. Please note this callback will be valid only when the query
prop is not used.
If you want to update your widget only when the selected records changes, you can use on
callback.
If your widget must load data, pass in the query
and widget
props. The widget
is required because the framework uses this prop to manage the query parameters that multiple widgets apply to the same data source.
If you want to load data but do not want to change the data in the data source, pass in the local
prop. This will create a local data source for use. The recommended localId pattern is: widget
, for example widget
.
When you render the Data
, the data source instance will be created but the data is not loaded initially because it's expecting you to pass in a query
prop which would cause another network request. To get the loaded data, you can use data
.
The data is paged and the default paging size is 100. The user can change the paging size in the builder data settings panel. The loaded data is cached on the client, and the cache will be cleared if the query criteria is changed.
When displaying the data, the displayed page size does not need to be the same as the query page size. For example, if the query paging size is 100, you can use data
to get the first 10 records to display.
To get the total number of records, pass in the query
prop, then get the count through data
.
Whenever the data source info is changed, the data render function and the on
callback will be invoked. The info includes the following:
instance
: whether the data source instance is created successfullyStatus status
: whether the data is loading or loadedcount
: whether the count of data is loading or loadedStatus selected
: the selected data IDsIds select
: the query (filter) to select data, the data source will query it and put the results in theOptions selected
Ids widget
: the query (filter) widgets applied to the data sourceQueries version
: the version number is used to manage the data change in the client side. Therefore, the data source consumers are aware when data is changed.gdb
: for feature services that support branch versioning. When the Branch Version Management widget switches the branch version, the version is saved here.Version
In many cases, the widget will need to compare the current data source info with the previous info to determine what needs to be updated.
If your widget needs to listen to the data source info change, but does not need to use the data records in the data source, you can omit the query
param and use the on
callback to do the query.
To get the fields in the data source, you can use data
.
Filter or query data based on user input
When a widget filters the data, the data in the data source instance is changed and all widgets will observe the change. When a widget queries data through a data source, the data in data source instance is not affected.
When multiple widgets apply a filter to the same data source, the attribute filters are tied together with and
operator(s). For geometry filters, the filter from the last widget (ordered by widget add order in the app config) to apply a geometry filter is used. For temporal filters, the intersection of time extents is used.
-
To filter a data source, there are two basic ways, depending on how the data source is configured:
- If the widget loads data, the recommended way is to use the
Data
like:Source Component
Use dark colors for code blocks Copy <DataSourceComponent useDataSource={} widgetId={} query={}> { Your render method } </DataSourceComponent>
You can find an example of using the
Data
in the Message subscriber sample and the Server-side output data source sample.Source Component Note: you can use
data
to load and filter the data as well.Source.load() - If the widget does not load data, you can use the
update
function of aQuery Params() Data Source
. See the Filter feature layer sample for an example.
- If the widget loads data, the recommended way is to use the
-
To query data through a data source, you can use
data
. When querying data, the filters applied to this data source are used as well.Source.query()
Handle selection on data
The designed selection behavior in an Experience Builder app is that all widgets should update and observe the same selection. For example, when a user selects a record within a List widget, the Text widget should see the selection if it uses the selection view. Every data source has a selection data view that manages the selection. Besides the selection data view, the selected record ID is saved in the Redux app store so widgets that use the data source can get notified when the selection is changed.
To select data records in a data source, you can use data
, data
or data
.
When using data
or data
, if the records have been loaded in the data source, you don't need to pass in the second parameter. If not, you need to pass in the second parameter to make sure other widgets that use the selections can read the records.
data
can select data records by a query parameter. The data source will set the query result to the data source info so that other widgets can be updated accordingly.
To read the selection, you can use data
.
Use WebMap/WebScene
WebMap and WebScene from the ArcGIS Maps SDK for JavaScript are wrapped as data sources in the jimu-arcgis
package. To access a WebMap, use Web
; to access a WebScene, use Web
. Review the MapView sample to learn how to use these data sources. In addition to the WebMap and WebScene objects, all the layers in these objects are wrapped as data sources as well, which allows you to call get
to get all the layer data sources. The supported layers and services are defined by Supported
and Supported
.
If you have a ArcGIS Maps SDK for JavaScript layer
and want to find the related layer data source, please call map
or map
. If you want to get child data sources of a specific data source type, please call map
.
Please note that if you create a map data source (Web
or Web
) by the Data
or the Data
, after the app is launched, the child data sources of it won't be created automatically. To create all child data sources, please call await map
.
Use FeatureLayer
In some workflows, you will be required to create a lightweight Experience that works with feature layers directly. In this scenario, you will use the Feature
classes. In general, a widget using a standalone feature layer will get a Feature
object without the layer
property, however using a feature layer from a webmap or webscene will return a Feature
object with the layer
property. The layer
object is from the ArcGIS Maps SDK for JavaScript.
To get the popup info, use feature
, to get the ID field, use feature
, to get the geometry type, use feature
.
const getLayerObject = (ds: FeatureLayerDataSource) => {
return ds.layer; // this can be null
}
Sharing data between widgets
Widgets will often share the same data. A good illustration of this is using a Map and List widget in an experience. When a feature is selected in the List widget, the corresponding feature is selected on the map. The easiest way to accomplish this is to use the same data source for both widgets. For example, when an item is selected in the List widget, the widget will call datasource.select
to update the data source info in the app store.
This allows the Map widget to render the currently selected item accordingly. In addition, the currently selected item ID will be placed in the URL, which enables you to share the current app state with others.
Sync the data source with the ArcGIS Maps SDK for JavaScript feature object
In an Experience Builder widget you can use the ArcGIS Maps SDK for JavaScript to get features. Then you may want to allow other widgets to use those features. For example, you may need to highlight these features on map, or show these features in List widget. You have 3 options to do this, listed below.
- Select these feature records in a data source
- If there is a data source instance you can use, you can just call
data
to select these records. If what you get is aSource.select Records By Ids() Graphic
instance, you need to create aFeature
instance first (Record feature
).Layer Data Source.build Record(graphic)
- If there is a data source instance you can use, you can just call
- Generate an output data source from your widget
- See the Widget output data source sample.
- Publish a message
- If your widget generates some features, you can publish the
Data
message so other widgets can subscribe.Record Set Change Message
- If your widget generates some features, you can publish the
Work with MapView/SceneView or LayerView
In many cases, when your widget works with a data source, it may need to work with MapView/SceneView as well. After the widget gets a Jimu
instance through Jimu
, you can get the corresponding data source of the MapView/SceneView by jimu
, and you can get the related layers through jimu
. Through the Jimu
instance, you can get the corresponding data source of the layer view by jimu
as well. Generally, to get a feature from a layer to sync with a data source, you have these options:
- Use the ID field of the feature to find the related data records in the data source
- Create a data record through the feature by creating a
Feature
instanceData Record - From a
Feature
instance, you can get the feature by usingData Record feature
Data Record.get Feature()