What is a data source?
A data source in ArcGIS Experience Builder defines how your widget accesses and manages data. Data sources provide a standardized way for widgets to interact with data types, whether from remote servers, local collections, or generated by other widgets.
Data sources serve as the bridge between your widgets and data, handling:
- Remote data access: Querying data from external services and databases.
- Local data management: Storing and managing client-side data collections.
- Widget communication: Sharing data between widgets through output data sources.
Data source structure
Every data source has a consistent structure with these components:
- Schema: Defines the structure and fields of the data.
- Records: contains the data queried from the source according to the current query criteria, can use the
getto get it.Records() - Status: Indicates the data source instance status and the data loading status. For the instance status, it includes the
Not,Created Created, andCreate. For the data loading status, it includesError Not,Ready Unloaded,Loading,Loaded,LoadError - Type and ID: Identifies the data source type and unique identifier.
The Data interface, defined in the jimu-core package, provides these methods:
id: The unique identifier for the data source.type: Property used to identify the data source type.get: Accesses the data source schema and fields.Schema() get: Retrieves data records from the data source.Records() get: Returns the current status (Status() Not,Ready Unloaded,Loading,Loaded,Load).Error
Data Source Management: Data sources are managed by the Data to create and get data sources. The data source object is managed in Data, while the data source info is managed in a redux app store. When using Data, the component calls Data to create the data source on demand and returns the data source object and data through a callback prop. The data source configuration is saved in the app, and the data source instances are managed by the data source manager.
DataSourceComponent: This component simplifies data source usage by accepting a use property and returning the data source object and its status info through a callback. It also accepts a function as its child, which can be used to get the data source object and info to render the data. The component can accept an optional query property and will reload the data when the query changes.
Data source types
Experience Builder provides many types of data sources to handle different data scenarios, below are some important data source types:
- QueriableDataSource: For data services that support querying operations
- ArcGISQueriableDataSource: For ArcGIS services with common query behaviors
- FeatureLayerDataSource: For accessing feature layer data
- MapServiceDataSource: For map service data access
- FeatureServiceDataSource: For feature service data access
- WebMapDataSource: Wraps WebMap from ArcGIS Maps SDK for JavaScript
- WebSceneDataSource: Wraps WebScene from ArcGIS Maps SDK for JavaScript
How to use data sources
Here are the steps to work with data sources in your widgets:
1. Select a data source
To select a data source for your widget:
- Use the
Datacomponent in your widget settingsSource Selector - Choose from available data sources or add new ones
- Configure the data source properties as needed
2. Configure data source
Configure how your widget uses the data source:
- Setting query parameters to filter the data
- Specifying which fields to retrieve
- Configuring pagination and caching options
3. Access data
Access data in your widget using:
- DataSourceComponent: Recommended approach for most scenarios
- Direct methods: Use
dataorSource.load() datafor specific needsSource.query() - Status monitoring: Check data source status before accessing data
Advanced data source concepts
Advanced data source concepts provide patterns for composing, scoping, and sharing data so widgets can work efficiently and independently. They include data source sets, data views, local data sources, source records, and widget output data sources. Despite their differences, each still conforms to the Data interface and is created, tracked, and updated through the Data, giving you a consistent API for querying, loading, filtering, and status management.
Data source sets
A Data is a data source that contains child data sources, making it easier to work with related data collections. Web is a Data.
Key features of data source sets:
- Contains multiple related data sources
- Child data sources are created on demand
- Use
getto retrieve child data sourcesChild Data Sources - Use
parentto access the parent data sourceData Source - Create child data sources with
createData Source By Id(ds Id)
Data views
Data views provide local views of data sources, similar to views in relational databases. They allow multiple widgets to work with the same data source while maintaining different perspectives.
Data view characteristics:
- Created from a main data source
- Share the same interface as data sources
- Selection is shared between main data source and all views
- Use
getto access the main data sourceMain Data Source
Local data sources
Local data sources and data views allow widgets to work with filtered data without affecting the original data source. This is useful for scenarios like dropdown lists that need different data views.
To use local data sources:
- Use
Datawith aSource Component localparameterId - Use
DataSource Manager().getinstance().create Local Data Source() - Filters applied to local data sources do not affect the original data source
Widget output data sources
Widgets can generate output data sources that other widgets can consume. This enables data flow between widgets in your application.
To create output data sources:
- Save the output data source configuration in your widget settings using
this.props.onSetting Change - The output data source is saved in the
datasection of the app configSources - Other widgets can use the output data source like any other data source
Important: When an output data source is created, its status is Not. The widget that generates the output data source should update the data source when the data is ready, and then change the data source status to Unloaded so other widgets know it is ready to use.
Output data source types:
-
Server-side: Connects to remote services
- Use
outputDs.update Query Params(query Params, widget Id) - Use
outputDs.load(query Params, { widget Id }) - Use
<DataSource Component use Data Source={ Immutable({ data Source Id : output Ds Id, main Data Source Id : output Ds Id })} query={query Params} >
- Use
-
Client-side: Stores data locally
- Use
outputto set the source if you have some featuresDs.set Source Features(features, options) - Use
outputto set the source if you have some data source recordsDs.set Source Records(records)
- Use
The origin property in the output data source JSON maintains the relationship between the origin data source and the output data source. If an output data source for a widget does not have a schema defined, the schema of the origin data source will be used.
Data querying and filtering
Loading and filtering data
When working with data sources, you have options for data access:
- Loading data: Use
DataorSource Component datafor data loading with caching and pagination. TheSource.load() loadmethod updates the data and status of the data source. - Filtering data: Use
datato apply filters without reloadingSource.update Query Params() - Querying data: Use
datafor queries that return records. TheSource.query() querymethod queries and returns records without updating the data source status.
Field selection
Optimize performance by selecting only the fields you need:
- Multiple records, few fields: Save field configuration in the
widgetin settingsJson.use Data Sources[i].fields - Single record, many fields: Use
datawith record IDSource.query() - Custom field selection: Set
outproperty in query parametersFields
Client-side querying
When working with map layers, data sources can perform client-side queries for performance:
- Queries are executed against the
Mapinstead of remote serversView - Falls back to server queries if
MaporView Layeris not readyView - Use
notto prevent performance issues with many fieldsAdd Fields To Client - Before performing client-side queries, the
Layeradds theView outfrom query params to theFields LayerfieldsView
Code examples
Here are some code examples for working with data sources:
To select a data source for your widget use the Data component in your widget settings
<DataSourceSelector
mustUseDataSource
types={Immutable([DataSourceTypes.FeatureLayer])}
onChange={(useDss: UseDataSource[]) => {
props.onSettingChange({
id: props.id,
useDataSources: useDss
})
}}
useDataSources={props.useDataSources}
widgetId={props.id}
/>Access data in your widget using Data which is the recommended approach for most scenarios:
<DataSourceComponent
useDataSource={props.useDataSources[0]}
widgetId={props.id}
query={customQueryParameters}
>
{
(ds, info: IMDataSourceInfo) => {
return <div>
<div>Query state: {info.status}</div>
<div className='record-list'>
{
ds
? ds.getRecords().map((r, i) => {
return <div key={i}>{r.getData()[props.config.fieldName]}</div>
})
: null
}
</div>
</div>
}
}
</DataSourceComponent>To create output data sources, save the output data source configuration in your widget settings using this.props.on:
onChange = () => {
const outputDsJsons: DataSourceJson[] = [{
id: `${props.id}-ouput`,
type: DataSourceTypes.FeatureLayer,
sourceLabel: `${props.manifest.name}-output-data-source`,
isOutputFromWidget: true,
geometryType: 'esriGeometryPoint',
originDataSources: [useDataSources[0]], // Optional, set it if creating this output data source depends on other data sources.
schema: schema, // Optional, set it if the output data source is client-side (without url).
url: 'https://<root>/<serviceName>/FeatureServer/<layerId>', // Optional
layerId: '<layerId>', // Optional
itemId: itemId, // Optional
portalUrl: portalUrl // Optional
}]
props.onSettingChange({
id: props.id
}, outputDsJsons)
}When an output data source is created, its status is Not. The widget that generates the output data source should update the data source when the data is ready, and then change the data source status to Unloaded so other widgets know it is ready to use.
onFeaturesChange = (features: IFeature[]) => {
const outputDs = DataSourceManager.getInstance().getDataSource(this.props.outputDataSources?.[0])
if (!outputDs) return
// If the output data source is client-side (without url), you can update its records by this way.
outputDs.setSourceRecords(features.map(f => outputDs.buildRecord(f)))
// Status of output data source is NotReady by default, set it to Unloaded to let other widgets know output data source is ready to do query.
outputDs.setStatus(DataSourceStatus.Unloaded)
outputDs.setCountStatus(DataSourceStatus.Unloaded)
}Data actions
Data actions allow widgets to perform operations on data sources. For information about implementing data actions, see Data action.
Repeated data sources
Repeated data sources work similarly to React Context, allowing parent widgets to provide data to child widgets.
To use repeated data sources:
- Access via
this.props.repeatedData Source - Contains
id,record, andrecordpropertiesIndex - Use
Repeatedto provide repeated data sourcesData Source Provider - Add
supportproperty to your widget manifest fileRepeat
The List widget is an example of a widget that provides repeated data sources.