ArcGIS for Developers

Core concepts

Introduction

Experience Builder can be extended through building custom widgets, creating custom themes, custom data sources, and message/actions. All of this is possible by using Experience Builder's extensibility framework called jimu, which is built on the following components:

  • ArcGIS API for JavaScript 4.x
  • React + Redux framework
  • Bootstrap 4 for user interface
  • HTML5

TypeScript is required to develop widgets, themes, etc. in Experience Builder. It provides many advantages such as:

  • Instant type error detection
  • Better IDE Experience
  • Self-documenting code
  • More readable and easier to understand

Jimu

Jimu is a JavaScript library used to create a configurable experience and is the extensibility framework that consists of the following packages:

  • jimu-core package loads and parses the app config, then loads the layout, theme, and widgets based on the app config. To support this, this package defines several classes like WidgetManager, ConfigManager, ThemeManager, etc. Also, the jimu-core defines the interface of the widget, some common types, and some extension points, which are subject to be extended by other packages and widgets.
  • jimu-layouts package contains common implementations for layout widgets.
  • jimu-ui package contains all the UI components that experiences will utilize. Under the hood, it uses reactstrap and emotion-js. Additionally, more components that are not in reactstrap are added. To reduce the loading size, the components are split into some entries, such as index, setting-components, sql-expression-builder, etc. See API for details.
  • jimu-arcgis package contains all the components that require the ArcGIS API for JavaScript 4.x to run.
  • jimu-for-builder package supports developing the widget setting page.

Data source

Data source defines how your widget accesses data. For example, when data is from a remote server, the widget can use a data source class to query the data to the client side. When data is generated by a widget, it can be used by another widget by putting itself into a data source class.

At a high level, a data source has a schema, some records, and may have some child/parent data source. In addition, every data source has a type, id, and status to help identify it. The DataSource interface is defined in the jimu-core package; it defines some of the following methods and properties:

  • id: the data source id.
  • type: property used in the widget to check which type of data source it is using.
  • fetchSchema: every data source must implement this method to return the schema. This is the schema defined in the remote data service. For example, when a user adds a data source in Experience Builder, the data source schema is not saved in the app config; instead, the fetchSchema method is called to get the latest data source schema.
  • getSchema: method used by the widget to access the data source schema and fields in the data source.
  • getRecords: method used by the widget to access the data records in the data source.
  • getStatus: the widget will use this property to get the status of the data source. Some of these statuses include Loading, Loaded, and Error.

A data source can have sub data sources. As a result, you may include more than one data source to make it easier to use. This kind of data source is called a DataSourceSet. WebMapDataSource is a DataSourceSet. DataSourceSet is also a type of data source once the isDataSourceSet property is set to true. Data source is managed by the DataSourceManager to create and get data sources.

When multiple widgets connect to a single data source, a widget may want to see a local view of the data source. In this scenario, you would use a data view. The relationship between a data view and data source is very similar to the relationship between a view and a table in a relational database. Although a data source in Experience Builder is a view of the actual remote data source on the client-side, you can think of a data source as a table and data view as a view. An app creator can create a data view from a data source and connect a widget to the data view in the builder. At the API level, the data view is managed by using the DataSource class, so the data view has the same interface and behavior with the data source just with some attribute differences.

To simplify the use of a data source, a DataSourceComponent component is defined. This accepts the useDataSource property and returns 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 in the data source. The DataSourceComponent component can also accept an optional query property and will reload the data when the query is changed.

To support the most commonly used data formats such as a feature service, the API has a QueriableDataSource interface and an abstract class AbstractQueriableDataSource. This interface has properties including url, load and query etc. The difference between the load and query methods is such that load updates the records property and the status of the data source, while query queries and returns the records only.

More specifically, we define the FeatureLayerDataSource data sources in Experience Builder to access a feature layer. If the data source is created from a standalone feature layer, the object does not have layer property; If it's created from a feature layer contained in a webmap/webscene, the object will have the layer property, which is a FeatureLayer object from the ArcGIS API for JavaScript.

In general, a data source is saved in two places: the data source object is saved and managed in DataSourceManager, and the data source info is saved in a redux app store. When using DataSourceComponent, the component will call DataSourceManager to create the data source on demand, and return the data source object and dataSourceInfo by using a callback prop. In dataSourceInfo, the data source's instanceStatus, status, selectedIds, etc. can be returned.

Most of the ArcGIS server services are mapped to data source for easy access, such as MapServiceDataSource, FeatureServiceDataSource, etc. WebMap and WebScene in the ArcGIS API for JavaScript are wrapped as WebMapDataSource and WebSceneDataSource in the jimu-arcgis package.

Repeated Data source

The data source provided by RepeatedDataSourceProvider is called a repeated data source. All children widgets of the widget that provide a data source will receive the repeated data source. This is similar to React's Context. A widget can access repeated data source by this.props.repeatedDataSource. The repeated data source will get the data source's id, record, and recordIndex. Any widget can provide repeated data source by using RepeatedDataSourceProvider. The List widget in Experience Builder is a good example that provides a repeated data source. To use a repeated data source, add the supportRepeat property in a widget's manifest file.

Map/Scene View

The view concept is the same as the ArcGIS API for JavaScript, however in Experience Builder, the view is wrapped as JimuMapView to ensure a consistent extensibility model when creating widgets, message/actions, etc. To create a JimuMapView object, a widget can use the JimuMapViewManager.createJimuMapView() method. A JimuMapView object has these main properties:

  • view: the map/scene view object.
  • datasourceId: the data source (webmap/webscene) that creates the view
  • mapWidgetId: the widget that creates the object
  • jimuLayerViews: the layer view object wrapper

The widget that needs to use the map/scene view can use the JimuMapViewSelector component in the setting page to select a map/scene view. This will also use JimuMapViewComponent to access the JimuMapView object.

Page

The page in an experience is not a physical HTML web page; it is a conceptual page, however, it behaves like an actual HTML web page. It is implemented by using a div HTML tag. An experience must have at least one page, and it can have multiple pages. There are two types of page layouts in Experience Builder: a full screen app page and a linear scrolling page; the former one looks like an application and the latter one looks like a web page.

The page contents (widget/section) are organized by layout rules, such as a fixed layout and flow layout. To make the page responsive on different screen sizes, Experience Builder supports the configuration of layouts by size modes. These are defined by Large, Medium, and Small. The configuration of each layout is an adaptation of the experience, which offers greater flexibility with more customization of the application and better usage of the screen size. A good illustration of this design is the City Explorer template. When the application is viewed on a large and medium screen, the map is visible and is included in the configuration; however, when it is viewed on a mobile device, the map widget is removed from the first page and is only displayed on the second page after a user selects a feature in the list widget.

Window

The window is similiar to a page, you can add any widget to it and it has two configurations for displaying content: fixed and anchored. The fixed window creates a modal that disables the main window but keeps it visible so users can interact with the window before they can return to the experience. A fixed window can be used as a splash screen, opened with a page or from a widget. An anchored window is triggered from a widget such as a button or a text widget.

Theme

Theme defines an experience's looking and feel. Experience includes out-of-the box(OOB) themes, and custom themes can be created. Learn more about theme development.

Widget

A widget is a configurable functional unit. It is the building block used to create pages for an experience. Experience Builder provides OOB widgets, such as map, button, list, etc., and custom widgets can be created. A widget usually provides a setting UI to allow users to configure its functionality in the builder environment. If a widget has configurable options but does not include a setting UI, a JSON editor can be used to configure it.

Learn more about widget implementation.

Message and action

Message/action is a way to support communication between widget to widget, widget to framework, and framework to widget. Widget/framework can publish a message, and they can listen to a message as well. A message is identified by MessageType, which is defined by the jimu framework. There are some message types defined in jimu, such as ExtentChange and DataRecordsSelectionChange. There will be more message types in future releases.

Learn more about how to create a message/action.