A widget in ArcGIS Experience Builder is a functional unit: a widget focuses on a single pice of functionality. In many cases, however, we need multiple widgets to work together to complete a task. To do this, we need ways to allow widgets to communication with each other at the framework level. This can be accomplished in Experience Builder in the following ways:
- Configurable:
- Use the same data source/data view between widgets
- Use a widget's output data source
- Use message/actions
- Use data actions
- Programming:
- Use widget state to share state between widgets
- Provide your own redux store/action/reducer to share state between widgets
Configurable means the user can config the way of communication between widgets in the builder. Programming means the communication between widgets happens in the code.
1.1 Use the same data source/data view between widgets
If multiple widgets use the same data source or data view, they can get the same selection, the same data records, and the same data source status. Widgets can use these data to sync status. For example: multiple widgets can read the same data record but display a different view; one widget can let the user do the selection and another widget can listen to the selection to display the selected data detail.
If multiple widgets use the different data views of the same data source, they still can get the same selection if the selection satisfies the data views filter criteria.
1.2 Use a widget's output data source
1.3 Use message/actions
See Message action for details.
1.4 Use data actions
See Data action for details.
2.1 Use widget state to share state between widgets
A widget, as a React component, can have an internal state. However, other widgets cannot access this state. Jimu uses Redux as its state manager; it saves a lot of info in the Redux store. One piece of the info is called widgets
; you can find the type definition at jimu-core/lib/types/state
. The info stored in widgets
is accessible by all of the other widgets.
To save some info in the widgets
, please refer to this code snippet:
import {appActions} from 'jimu-core';
/*
* Call this when you need to save state.
*
* widgetId: your widget id
* propKey: can be a string with this format "a.b.c"
* value: the info you want to store
*/
this.props.dispatch(appActions.widgetStatePropChange(widgetId, propKey, value))
For example, if you call this.props.dispatch(app
and this.props.dispatch(app
, you'll get this store state in the Redux store:
widgetsState: {
w1: {
a: {
b1: 'value1',
b2: 'value2'
}
}
}
To access the data stored by w1
in widget 2, you can select the value from store by using map
or using use
hooks.
widgets
can only store plain (e.g. does not have functions) JavaScript objects. To store complex (e.g. created from a function constructor or has function members) JavaScript objects, you can use this.props.dispatch(app
to store the value, and use Mutable
to access it.
2.2 Provide your own redux store/action/reducer to share state between widgets
This provides a more flexible way to customize your state management. You can find this is almost the same as the Redux approach. As we know, Redux has only one store and one root reducer, which is used by jimu. To let the widget developer use the normal Redux approach to manage state, jimu defines a Redux
extension point; widgets that need to use Redux can provide an extension for this extension point.
- Create an extension class to implement the
Redux
interface; let's call itStore Extension my-store.ts
.
import {extensionSpec} from 'jimu-core';
export default class MyReduxStoreExtension implements extensionSpec.ReduxStoreExtension{
getActions(){
// return your redux actions.
}
getInitLocalState(){
// return your redux init local state.
}
getReducer(){
// return your redux reducer.
}
getStoreKey(){
// return your redux local key.
}
}
- Declare the extension in widget manifest.json
"extensions": [
{
"name": "My Store",
"point": "REDUX_STORE",
"uri": "my-store"
}
]