The ArcGIS Experience Builder framework is designed to be extensible. As a developer, you can extend Experience Builder in various ways, such as creating custom widgets and themes. In addition to these, you can also create deeper customizations using Jimu extensions.

What is an extension point?

An extension point in the Experience Builder Jimu library is a named contract that defines how developers can extend framework behavior. An extension is a class that implements the interface for a specific extension point.

The base interface is BaseExtension for all extensions. Each extension has its own interface, which extends from the base interface. For example, the extensionSpec.AppConfigProcessorExtension interface exported from jimu-core is used for the AppConfigProcessor extension point.

To provide an extension in a widget, you must declare it in the widget's manifest.json file.

Why use an extension point?

An extension point allows you to hook into the Experience Builder framework and modify or enhance its behavior in ways that are not possible through standard widget development. For example, you can use an extension to:

  • Modify the app configuration before any other widgets get loaded at runtime
  • Integrate third-party libraries that require initialization
  • Define custom Redux actions and reducers for your widget

How to implement an extension

To implement an extension, you need to:

  1. Create a class that implements the extension point interface defined in the extensionSpec.
  2. Export the extension class from a file in your widget's src folder.
  3. Declare the extension in your widget's manifest.json file under the extensions section. For example:
Use dark colors for code blocksCopy
1
2
3
4
5
6
"extensions": [
  {
    "point": "<Extension point name>",
    "uri": "<Extension uri, relative to src folder>"
  }
]

Types of extension points

Jimu defines a variety of extension points that are documented in the API reference. Some commonly used extension points include:

Extension point nameDescription
AppConfigProcessorExtensionThe extension for this extension point receives the AppConfig and should return a promise that resolves the processed app config. This can be used to make runtime modifications to the app config, like translating strings (see the Translation sample). The process will be invoked just after app config is loaded.
BuilderOperationsExtensionUsing this extension you can hook into builder operations, such as saving and publishing apps.
ReduxStoreExtensionUsing this extension you can extend the Redux store for your widget by retrieving properties such as actions, reducers, initial state, and a store key.

Code examples

Translate strings in the app config

This example shows how to implement the AppConfigProcessorExtension extension point to translate strings in the app config at runtime.

The extension declares the extension in manifest.json:

Use dark colors for code blocksCopy
1
2
3
4
5
6
"extensions": [
    {
      "point": "APP_CONFIG_PROCESSOR_EXTENSION",
      "uri": "extensions/translation"
    }
  ]

In the translation.ts file, the AppConfigProcessorExtension interface is implemented to process the app config and replace the i18n placeholders with translated strings.

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import { type extensionSpec, type AppConfig, utils, createIntl, getAppStore } from 'jimu-core'
import defaultMessage from '../runtime/translations/default'

export default class Translation implements extensionSpec.AppConfigProcessorExtension {
  id = 'translation'
  widgetId: string

  async process (appConfig: AppConfig): Promise<AppConfig> {
    // Do not replace when run in builder.
    if (window.jimuConfig.isInBuilder) {
      return Promise.resolve(appConfig)
    }
    const widgetJson = appConfig.widgets[this.widgetId]

    const intl = createIntl({
      locale: getAppStore().getState().appContext.locale,
      messages: Object.assign({}, defaultMessage, widgetJson.manifest.i18nMessages)
    })

    utils.replaceI18nPlaceholdersInObject(appConfig, intl, defaultMessage)
    return Promise.resolve(appConfig)
  }
}

The code above:

  1. Defines a class Translation that implements the AppConfigProcessorExtension interface.
  2. The process method checks if the app is running in the builder, and if not, it creates an internationalization (intl) object using the current locale and messages from the widget manifest.
  3. It then calls utils.replaceI18nPlaceholdersInObject to replace the placeholders in the app config with the translated strings, and returns the modified app config.

Your browser is no longer supported. Please upgrade your browser for the best experience. See our browser deprecation post for more details.