Watch for changes

Watching for changes on properties in the ArcGIS Maps SDK for JavaScript is essential for detecting and implementing custom responses to those changes in your application. You can track changes in two ways. Use component lifecycle methods and events to know when a component or its view is ready and respond to high-level UI actions. And use reactiveUtils to observe property and state changes on both components and core API objects for more detailed control.

Component readiness and events

Components expose lifecycle methods and events that let you know exactly when they are ready and when key changes occur.

Waiting for components or views to be ready

Sometimes you need to interact with a component as soon as it is available or once the view is fully initialized. Use the component lifecycle methods componentOnReady() and viewOnReady() to provide a way to wait for the right state before executing logic.

The components <arcgis-map>, <arcgis-scene>, and <arcgis-link-chart> expose a view property, which is only available once the internal MapView, SceneView or LinkChartView has been initialized. To know when the view is ready, use the viewOnReady() method. This method returns a promise that resolves when the view is available.

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
<arcgis-map item-id="332e5d145bec4c2c860d65f7ca494b23" center="0,0" zoom="7" id="mapEl"></arcgis-map>

<script type="module">
  const viewElement = document.getElementById("mapEl");

  // Wait for the internal MapView to be ready
  await viewElement.viewOnReady();
  console.log("MapView is ready:", viewElement.view);
</script>

This is useful when you are dynamically importing other modules or setting up logic that depends on the view being fully initialized.

Unlike viewOnReady(), which is specific to components that expose a view, the componentOnReady() method is available on all components, including calcite components. It returns a promise that resolves once the component is fully hydrated and ready for interaction. This means:

  • the component has rendered at least once
  • it's public properties and methods are available for use

Use this before calling whenLayerView() to interact with a layer independently of the view, or setting properties such as search.allSources to configure and use the search component.

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<arcgis-map item-id="45725ba7d9fb47a0925398919b13d1fa">
  <arcgis-search position="top-left"></arcgis-search>
</arcgis-map>

<script type="module">
  const searchElement = document.querySelector("arcgis-search");
  await searchElement.componentOnReady();

  searchElement.allSources.on("change", () => {
    searchElement.allSources.forEach((source) => {
      source.zoomScale = 100000;
    });
  });
</script>

Using component events

Components may emit information about changes to their state as events. The changes can be initiated by internal changes, user interaction or when setting properties or attributes. Listen for events by using the addEventListener method. The event's payload contains information about the change event, such as the action that was triggered, the item that was clicked, or the new state of the component.

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
const arcgisLayerList = document.querySelector("arcgis-layer-list");
arcgisLayerList.addEventListener("arcgisTriggerAction", async (event) => {
  // event.detail is used here since the event type is CustomEvent<LayerListTriggerActionEvent>
  // It returns data passed when initializing the event.
  // https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/detail
  const { action, item } = event.detail;
  await item.layer.load();
  if (action.id === "information") {
    // do something;
  }
});

Map interactions such as panning, zooming, clicking and dragging can be tracked using events. For example, to watch for view-related property changes, such as zoom, on the arcgis-map component, use the arcgisViewChange event.

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
const viewElement = document.querySelector("arcgis-map");
viewElement.addEventListener("arcgisViewChange", (event) => {
  // event.target provides a reference to the object that dispatched the event
  // event.target is used here since the event type is CustomEvent<void>
  // The void means that there are no details provided by the event, itself.
  const { zoom } = event.target;
  console.log(`The zoom is ${zoom}`);
});

The arcgisViewReadyChange event is particularly useful for detecting when a Map, WebMap or WebScene has been initially loaded or updated on the arcgis-map or arcgis-scene component. Here are the scenarios that trigger arcgisViewReadyChange:

  • Initial load: When the arcgis-map or arcgis-scene component's map is initially set, the event will fire once the view is ready.
  • Updates: If the map of a map or scene component is replaced with either a Map, WebMap, or WebScene, the event will fire again. Changing the item-id will also trigger the event, signaling that a new WebMap or WebScene has been loaded.
Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
const map = document.querySelector("arcgis-map");

map.addEventListener("arcgisViewReadyChange", () => {
  console.log(`New WebMap loaded with itemId: ${map.itemId}`);
  // Perform actions based on the newly loaded WebMap
});

// Example of switching the WebMap after a delay
setTimeout(() => {
  map.itemId = "new-webmap-id";
}, 3000);

The arcgisPropertyChange event allows for the monitoring of property changes in non-view-based components. For instance, in the arcgis-area-measurement-2d component, the arcgisPropertyChange event can be used to track the state of the measurement process, such as when a user initiates or completes a measurement.

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
const areaMeasurement = document.querySelector("arcgis-area-measurement-2d");

areaMeasurement.addEventListener("arcgisPropertyChange", (event) => {
  if (event.detail.name === "state") {
    console.log("Measurement state:", event.target[e.detail.name]);
  }
});
Choosing the right readiness method or event for your app

The components provide multiple ways to know when they're ready to be interacted with. Depending on your application type — whether it's a vanilla JavaScript application or a framework-based application (like React, Vite, or Angular) — you should choose the readiness method that best fits your architecture.

Method / EventApp typeApplies toDescription
viewOnReady()Vanilla JavaScriptView-based components (<arcgis-map>, <arcgis-scene>, and <arcgis-link-chart>)Returns a promise when the view (MapView or SceneView) is ready. Best used when you need an explicit way to wait for the view, especially if there is a risk the event has already fired before your code runs.
arcgisViewReadyChangeFrameworkView-based components (<arcgis-map>, <arcgis-scene>, and <arcgis-link-chart>)Event that fires when the view is assigned. Preferred usage is to register the event handler early in the framework's component lifecycle.
arcgisReadyAnyAll components, except view-based componentsEvent that fires when both map and view are ready. Useful to know when that map and view are ready to interact with component (e.g., add layers, set center, etc.)
componentOnReady()AnyAll components (including Calcite)Returns a promise when the component is defined and hydrated.

Use this table to help choose the most appropriate readiness pattern based on the type of application you're building and the specific component you're working with.

Explore the watch for changes with components sample to see these events and methods in action.

Observing property changes with reactiveUtils

reactiveUtils provides the ability to simultaneously track property and state changes in both component and API properties. For example, you can track a component’s lifecycle, navigation state, and UI settings. Within the core API you can track the status of views, layers, layer views and more.

reactiveUtils works with all of the SDK's property types including strings, booleans, arrays, collections, and objects. Properties can also be combined from multiple sources. The following methods are included: watch(), on(), once(), when(), and whenOnce().

reactiveUtils also provide TypeScript type checking. You can access properties, build objects or perform other calculations and it is all properly checked by the TypeScript compiler. Callback parameters are correctly inferred from the getValue() function.

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
28
29
30
31
32
33
34
35
36
37
38
39
const reactiveUtils = await $arcgis.import("@arcgis/core/core/reactiveUtils.js");

const viewElement = document.querySelector("arcgis-map");

// Wait until the component is fully loaded
await viewElement.componentOnReady();

// Wait until the layer view is ready on a feature layer
const layerView = await viewElement.whenLayerView(featureLayer);

// Wait until the component's view is ready
// as determined by the ready property becoming truthy.
// whenOnce() returns a promise.
await reactiveUtils.whenOnce(() => viewElement.ready);

// Watch for changes to both the extent and navigation properties
// Extent is an object and navigation is a boolean
reactiveUtils.watch(
  // getValue function
  () => [viewElement.extent, viewElement.navigating],
  // callback function
  (result) => {
    console.log(`Extent: ${JSON.stringify(result[0])}, navigating: ${result[1]}`);
  });

// Watch for when the stationary property becomes truthy
reactiveUtils.when(
  () => viewElement.stationary,
  () => {
    console.log("scale:", viewElement.scale)
  });

// Watch for changes on the layer's loaded property
// and the layer view's dataUpdating property.
reactiveUtils.watch(
  () => [layerView.layer.loaded, layerView.dataUpdating],
  (result) => {
    console.log(`Layer loaded: ${result[0]}, dataUpdating: ${result[1]}`);
  });

To see reactiveUtils in action, you can explore these samples:

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