Programming patterns

This topic covers common usage patterns and best practices for components and the core API when building applications with the ArcGIS Maps SDK for JavaScript.

Attributes and properties

ArcGIS Maps SDK for JavaScript components' HTML attributes and JavaScript properties, while similar in concept, have some key differences. HTML attributes are always strings and they can be set directly on the HTML element or programmatically in JavaScript. Even when setting what seems like a number, the attribute value is still a string. In HTML, the presence of an boolean attribute means it is true and its absence means it is false, such as drag-enabled in the snippet below. Setting attribute strings to "true" and "false" is invalid. Attributes are written in kebab-case, while properties are in camelCase.

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
<body>
  <arcgis-map id="my-map" item-id="05e015c5f0314db9a487a9b46cb37eca"></arcgis-map>
  <arcgis-layer-list
    reference-element="my-map"
    drag-enabled
    selection-mode="multiple">
  </arcgis-layer-list>
</body>

On the other hand, JavaScript properties can be any valid JavaScript data type, including strings, booleans, numbers, arrays, objects, functions, and more. Properties can only be set programmatically using JavaScript. Most properties have an associated attribute, but not all. If a property is any type besides a string, number, or boolean, it will not have an associated attribute.

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
24
25
26
27
// Get a reference to the arcgis-layer-list component
const arcgisLayerList = document.querySelector("arcgis-layer-list");

// Set properties with various data types

// arcgis-map component
arcgisLayerList.referenceElement = document.querySelector("my-map");
// boolean
arcgisLayerList.dragEnabled = true;
// function
arcgisLayerList.listItemCreatedFunction = (event) => {
  const { item } = event;
  if (item.layer.type != "group") {
    item.panel = {
      content: "legend"
    };
  }
};
// string
arcgisLayerList.selectionMode = "multiple";
// object
arcgisLayerList.visibleElements = {
  ...arcgisLayerList.visibleElements,
  ...{
    statusIndicators: false
  }
};

Boolean attributes

Boolean attributes present a special case in HTML elements. The presence of the attribute in an HTML tag always indicates a value of true, and absence of the attribute from the tag indicates a value of false. It is invalid to set a boolean attribute using the string values "true" or "false". Here is an example using the Map components popupDisabled attribute:

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
<!-- Best practice: set popupDisabled to true -->
<arcgis-map popupDisabled></arcgis-map>

<!-- Best practice: set popupDisabled to false (default) -->
<arcgis-map></arcgis-map>

<!-- Invalid: don't use strings to set boolean values -->
<arcgis-map popupDisabled="true"></arcgis-map>

More information is available in the Boolean attribute (HTML) MDN article.

HTML start and end tags

Components from the ArcGIS Maps SDK for JavaScript are standards-based custom HTML elements, which means they must have a start and end tag in HTML. They cannot be self-closing.

Use dark colors for code blocksCopy
1
2
3
4
5
<!-- Best practice: start and end tags -->
<arcgis-map></arcgis-map>

<!-- Invalid: self-closing tags -->
<arcgis-map />

Associate components with a Map or Scene component

The Map and Scene components are parent containers for building interactive 2D and 3D visualization experiences. Other components from the @arcgis/map-components package can be associated with a Map or Scene component to provide additional functionality, such as adding a legend, layer list, search, and more. There are two methods to associate components from @arcgis/map-components package to a Map or Scene component. The first method involves including the component as a child element of the Map or Scene component.

Use dark colors for code blocksCopy
1
2
3
<arcgis-map item-id="05e015c5f0314db9a487a9b46cb37eca">
  <arcgis-legend position="bottom-right"></arcgis-legend>
</arcgis-map>

The second is to use the reference-element attribute on the component. By passing the id of the Map or Scene component into this attribute, you can position components from the @arcgis/map-components package anywhere in the DOM while still maintaining a connection to the Map or Scene.

Use dark colors for code blocksCopy
1
2
<arcgis-map id="my-map" item-id="05e015c5f0314db9a487a9b46cb37eca"></arcgis-map>
<arcgis-legend reference-element="my-map"></arcgis-legend>

Configure Map and Scene components

When using the arcgis-map component, you can initialize it with either a Map or a WebMap. The arcgis-scene component can be initialized with either a Map or WebScene. The choice depends on whether you want to configure the functionality and layers programmatically (e.g. Map) or leverage pre-configured portal items (e.g. WebMap, WebScene).

Using the item-id attribute

The item-id attribute is used to specify the portal item ID of the WebMap or WebScene that you want to load into the arcgis-map or arcgis-scene component. When an item-id is provided to an arcgis-map component, the map property will be initialized with a WebMap instance.

Use dark colors for code blocksCopy
1
<arcgis-map item-id="05e015c5f0314db9a487a9b46cb37eca"></arcgis-map>

Using Map

You can add layers and configure the map programmatically. If no basemap is specified, a default basemap (topo-vector) will be loaded on the component's basemap property. This pattern is useful for applications where specific layers or properties must be added dynamically, for example:

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<body>
  <arcgis-map zoom="3" center="-100, 40">
    <arcgis-zoom position="top-left"></arcgis-zoom>
  </arcgis-map>
  <script>
    require(["esri/layers/Layer"], (Layer) => {
      const mapElement = document.querySelector("arcgis-map");
      mapElement.addEventListener("arcgisViewReadyChange", async () => {
        const url = "https://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer/2";
        const layer = await Layer.fromArcGISServerUrl({ url });
        mapElement.addLayer(layer);
        });
    });
  </script>
</body>

Using WebMap (or WebScene)

The WebMap automatically loads the layers and map configuration defined by the portal item ID, making it ideal for quickly adding maps that have been created in Map Viewer. Here is an example:

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
require(["esri/WebMap"], (WebMap) => {
  const mapElement = document.querySelector("arcgis-map");
  const webmap = new WebMap({
    portalItem: {
      id: "e691172598f04ea8881cd2a4adaa45ba"
    }
  });

  // Set a WebMap on the arcgis-map component's map property
  mapElement.map = webmap;

  mapElement.addEventListener("arcgisViewReadyChange", (event) => {
    const { map } = event.target;
    // Work with the WebMap
  });
});

To learn how to create a web map, you can follow this tutorial.

Position custom content on a map or scene component

The arcgis-map and arcgis-scene components can be used as containers for custom content, such as buttons, or other HTML elements. To add custom content, you can use the arcgis-placement component. This component allows you to position custom content on the map or scene using the position attribute.

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
<arcgis-map item-id="d5dda743788a4b0688fe48f43ae7beb9">
  <arcgis-placement position="bottom-left">
    <button>Click me</button>
    <arcgis-expand>
      <arcgis-legend></arcgis-legend>
    </arcgis-expand>
  </arcgis-placement>
</arcgis-map>

Configure global properties

You can use the global esriConfig variable to configure global properties of the JavaScript Maps SDK (API and components), such as the portalUrl.

Set the portalUrl in an AMD application

Importing esri/config is necessary to configure the global esriConfig object in AMD applications. The $arcgis global is a new promise-based way of importing modules in ArcGIS Maps SDK for JavaScript AMD projects without the need for require. The $arcgis global is available in the ArcGIS Maps SDK for JavaScript 4.28 and later for AMD projects.

AMD
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
24
25
<html>
  <head>
    <!-- Load the ArcGIS Maps SDK for JavaScript -->
    <link rel="stylesheet" href="https://js.arcgis.com/4.31/esri/themes/dark/main.css" />
    <script src="https://js.arcgis.com/4.31/"></script>
    <script>
      require(["esri/config"], (esriConfig) => {
        esriConfig.portalUrl = "https://myHostName.esri.com/arcgis";
      });
      // Optional: $arcgis global instead of require
      // async function load() {
      // 	const esriConfig = await $arcgis.import("esri/config");
      // 	esriConfig.portalUrl = "https://myHostName.esri.com/arcgis";
      // }
      // load();
	  </script>
    <!-- Load map components -->
    <script type="module" src="https://js.arcgis.com/map-components/4.31/arcgis-map-components.esm.js"></script>
  </head>
  <body>
    <arcgis-map item-id="d5dda743788a4b0688fe48f43ae7beb9">
      <arcgis-legend position="bottom-left"></arcgis-legend>
    </arcgis-map>
  </body>
</html>

Set the portalUrl in an ESM application

Importing @arcgis/core/config is necessary for configuring the global esriConfig object in ESM applications. Web maps hosted on a different portal can be initialized before being passed to the arcgis-map component:

ESM
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
24
25
26
import esriConfig from "@arcgis/core/config";
import WebMap from "@arcgis/core/WebMap";
import IdentityManager from "@arcgis/core/identity/IdentityManager";
import OAuthInfo from "@arcgis/core/identity/OAuthInfo";

const portalUrl = "https://myHostName.esri.com/arcgis";
const mapElement = document.querySelector("arcgis-map");

esriConfig.portalUrl = portalUrl;

// Bonus: register OAuth info
IdentityManager.registerOAuthInfos([
  new OAuthInfo({
    appId: "...",
    portalUrl
  });
]);

const webmap = new WebMap({
  portalItem: {
    id: "..."
  }
})

// Pass the webmap to the `arcgis-map` component
mapElement.map = webmap;

Localization

The language and direction of some web components, such as @arcgis/charts-components and @arcgis/coding-components, can be inherited from the root of the HTML document in the host application, the component itself, or the component's closest parent element. This is a bottom up approach. In cases where a language and direction are not provided, the component will default to left-to-right (ltr) and English (en). See locale support for the full list of supported languages.

Setting the language

Use the ISO language code for setting the language in the lang attribute.

Use dark colors for code blocksCopy
1
<html lang="fr"></html>

Setting the direction

You only need to do this for Arabic and Hebrew.

Use dark colors for code blocksCopy
1
<html dir="rtl" lang="he"></html>

Widget viewModel pattern

Additional functionality can be implemented using the viewModel for many of the widgets. Each widget has a view and a viewModel. The view is generally responsible for handling the User Interface (UI) of the widget, for example the Sketch widget. The viewModel is typically responsible for the business logic, for example SketchViewModel.

The viewModels extend esri/core/Accessor and take advantage of its capabilities. This helps keeps consistency between various parts of the API.

Widget state is derived from both view and viewModel properties. At some point within the widget's lifecycle, the view calls the viewModel's methods and properties. Changes to the viewModel can also trigger the view to update the UI.

Here is a code snippet using the SketchViewModel.polygonSymbol property to override the default drawing symbology:

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const polygonSymbol = {
  type: "simple-fill", // autocasts as new SimpleFillSymbol()
  color: "#F2BC94",
  outline: {
    // autocasts as new SimpleLineSymbol()
    color: "#722620",
    width: 3
  }
};

const sketchViewModel = new SketchViewModel({
  view: view,
  layer: graphicsLayer,
  polygonSymbol: polygonSymbol,
});

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