Using an ArcGIS JavaScript API-style Widget within a Custom Experience Builder Widget

2095
1
06-15-2020 01:03 PM
GavinRehkemper
Esri Contributor
4 1 2,095

We have received a few questions over the past few months about how to use "Custom ArcGIS API for JavaScript widgets" (like the Custom Recenter Widget) from within an Experience Builder widget. These are the current instructions on how to do that. There may be better or different ways - if you learn of one, please let us know!

Note: Last updated 2020-07 for ArcGIS JS API 4.16 and Experience Builder Developer Edition v1.1.

1. Build the JavaScript API Widget

Follow the instructions in the documentation for the ArcGIS API for JavaScript to Create a Custom Widget and then create the Custom Recenter Widget. These guides do not use webpack to package the files - they are only using the TypeScript compiler (tsc) to convert the *.tsx files to *.js files.

After you've run the tsc command to convert the tsx files to js files one last time, copy the JS file (Recenter.js) and move on - we will copy this into our custom Experience Builder widget in the next step.

2. Create a Custom Experience Builder widget

Create a new custom Experience Builder widget. The easiest way to get going quickly is probably to copy the simple widget.

Since the JS API Widget interacts with a Map View, your Experience Builder widget will need the infrastructure to reference a Map View widget within the same Experience app. The easiest way to do this is to create an Experience, add your widget, then go to the config for your working app (server\src\public\apps\Z\resources\config) and set "useMapWidgetIds": ["widget_ZZ"], in the widget config.

example config

In your widget manifest.json, include the jimu-arcgis dependency by adding:

"dependency": ["jimu-arcgis"],‍‍‍

Copy the JS file that you had from step 1 (Recenter.js) into your widget files, at the same level as widget.tsx (within src/runtime).

Within widget.tsx, import the file:

import Recenter = require("./Recenter");‍‍‍

Then utilize the Recenter widget within the callback of JimuMapViewComponent or anywhere you have an instance of the Map View:

render() {
  return (
    <div className="widget-demo jimu-widget m-2">
      {this.props.hasOwnProperty("useMapWidgetIds") &&
        this.props.useMapWidgetIds &&
        this.props.useMapWidgetIds.length === 1 && (
          <JimuMapViewComponent
            useMapWidgetIds={this.props.useMapWidgetIds}
            onActiveViewChange={(jmv: JimuMapView) => {
              if (jmv) {
                jmv.view.when(function () {
                  const recenter = new Recenter({
                    view: jmv.view,
                    initialCenter: [-100.33, 43.69],
                  });

                  jmv.view.ui.add(recenter, "top-right");
                });
              }
            }}
          />
        )}
      <p>Simple Widget</p>
    </div>
  );
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

For the above code to work, you'll need to import JimuMapViewComponent and JimuMapView at the top of your widget like this:

import { JimuMapViewComponent, JimuMapView } from "jimu-arcgis";

If successful, you'll see the info box in the top-right corner of the map when you add your widget to an Experience (and configure it manually to reference a map):

Next Steps

The next logical step would probably be to modify the widget to have the text inside the Experience Builder widget instead of on the map. I'll leave that up to you, and also please feel free to post other widgets and widget ideas you are building!

1 Comment
About the Author
I am a geospatial developer working for Esri Professional Services. https://gavinr.com ... see my Codepens: https://codepen.io/gavinr