What is a message action?
In ArcGIS Experience Builder, message actions are a mechanism for communication between widgets and the framework. Widgets and the framework can both publish and listen to messages, enabling dynamic interactions and workflows. A message is identified by a Message, which is defined by the jimu framework. Common message types include Extent and Data.
How to use message actions
Here are the general steps to use message actions in ArcGIS Experience Builder:
1. Declare messages and actions in manifest
To publish a message, a widget calls Message. For example, the List widget publishes the Data message when a list item is clicked, and the Map widget publishes the Extent message when the view changes.
Each message is defined by a class. For example, Extent defines the extent property as its payload.
To publish a message, declare the published messages in the manifest.json file:
"publishMessages": [
"DATA_RECORDS_SELECTION_CHANGE"
]2. Publish or handle messages
If a widget needs to publish message, it should call Message. If a widget needs to handle message, it should implement the actions.
To create a message action, extend the Abstract class. Several methods help you develop message actions:
-
filterMessageDescription: Filters available actions in the builder.
Use dark colors for code blocks Copy export default class QueryAction extends AbstractMessageAction { filterMessageDescription(messageDescription: MessageDescription): boolean { return [MessageType.StringSelectionChange, MessageType.DataRecordsSelectionChange].indexOf(messageDescription.messageType) > -1; } } -
filterMessage: Filters messages when the action receive messages in runtime.
Use dark colors for code blocks Copy filterMessage(message: Message): boolean { return true; } -
Setting UI: Some actions need a settings UI. Declare
settinginUri manifest.json. To skip the settings UI in specific cases, overridegetand returnSetting Component Uri null. -
Action setting UI component: This is a React component with injected props. When the user changes the config, call
this.props.onto save the config, which will be available inSetting Change on.Execute Use dark colors for code blocks Copy this.props.onSettingChange({ actionId: this.props.actionId, config: {} // the action config }) -
onExecute: Handles the logic for your message type. For example, dispatching a Redux action to update state:
Use dark colors for code blocks Copy onExecute(message: Message, actionConfig?: any): Promise<boolean> | boolean { let q = `${(actionConfig as ConfigForStringChangeMessage).fieldName} = '${message}'` switch(message.type) { case MessageType.StringSelectionChange: q = `${(actionConfig as ConfigForStringChangeMessage).fieldName} = '${(message as StringSelectionChangeMessage).str}'` break; case MessageType.DataRecordsSelectionChange: q = `${actionConfig.fieldName} = ` + `'${(message as DataRecordsSelectionChangeMessage).records[0].getFieldValue(actionConfig.fieldName)}'` break; } getAppStore().dispatch(appActions.widgetStatePropChange(this.widgetId, 'queryString', q)); return true; }
Only plain JSON objects can be stored in the Redux store. For complex objects, use Mutable:
MutableStoreManager.getInstance().updateStateValue(this.widgetId, 'theKey', theComplexObject)Access the object in your widget:
this.props.mutableStateProps.theKeyDeclare message actions in manifest.json:
"messageActions": [
{
"name": "query",
"label": "Query",
"uri": "actions/query-action",
"settingUri": "actions/query-action-setting"
}
]Configure i18n support
Internationalization (i18n) for message actions follows the same pattern as for widgets, with one key difference: message actions have a "Select an action" panel. You need a default.ts file in the runtime/translations folder with property names for your actions. The label property must use the naming convention _action.
export default {
_widgetLabel: 'Message subscriber',
_action_query_label: 'Query'
}Code example
Create a message action in a widget
This example shows how to use message actions in a widget.
Create a class to extend the AbstractMessageAction class.
export default class QueryAction extends AbstractMessageAction{
filterMessageDescription(messageDescription: MessageDescription): boolean{
return [MessageType.StringSelectionChange, MessageType.DataRecordsSelectionChange].indexOf(messageDescription.messageType) > -1;
}
filterMessage(message: Message): boolean{return true; }
getSettingComponentUri(messageType: MessageType, messageWidgetId?: string): string {
return 'actions/query-action-setting';
}
onExecute(message: Message, actionConfig?: any): Promise<boolean> | boolean{
let q = `${actionConfig.fieldName} = '${message}'`
switch(message.type){
case MessageType.StringSelectionChange:
q = `${actionConfig.fieldName} = '${(message as StringSelectionChangeMessage).str}'`
break;
case MessageType.DataRecordsSelectionChange:
q = `${actionConfig.fieldName} = ` +
`'${(message as DataRecordsSelectionChangeMessage).records[0].getFieldValue(actionConfig.fieldName)}'`
break;
}
getAppStore().dispatch(appActions.widgetStatePropChange(this.widgetId, 'queryString', q));
return true;
}
}Create a class extending React.. The configuration of the message action can be changed through the on method.
this.props.onSettingChange({
actionId: this.props.actionId,
config: this.props.config.set('fieldName', field['name']).set('useDataSource',{
dataSourceId: this.props.config.useDataSource.dataSourceId,
mainDataSourceId: this.props.config.useDataSource.mainDataSourceId,
dataViewId: this.props.config.useDataSource.dataViewId,
rootDataSourceId: this.props.config.useDataSource.rootDataSourceId,
fields: allSelectedFields.map(f => f.jimuName)
})
});In the manifest.json there is a message property that provides the location and information for the message action extension.
"messageActions": [
{
"name": "query",
"label": "Query",
"uri": "actions/query-action",
"settingUri": "actions/query-action-setting"
}
]