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 component
and view
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 Map
, Scene
or Link
has been initialized.
To know when the view is ready, use the view
method. This method returns a promise that resolves when the view
is available.
<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 view
, which is specific to components that expose a view, the component
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 when
to interact with a layer independently of the view, or setting properties such as search.all
to configure and use the search component.
<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 add
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.
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 arcgis
event.
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 arcgis
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 arcgis
:
- Initial load: When the
arcgis-map
orarcgis-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
,Web
, orMap Web
, the event will fire again. Changing theScene item-id
will also trigger the event, signaling that a new WebMap or WebScene has been loaded.
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 arcgis
event allows for the monitoring of property changes in non-view-based components.
For instance, in the arcgis-area-measurement-2d component, the arcgis
event can be used to track the state of the measurement process, such as when a user initiates or completes a measurement.
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 / Event | App type | Applies to | Description |
---|---|---|---|
view | Vanilla JavaScript | View-based components (<arcgis-map , <arcgis-scene , and <arcgis-link-chart ) | Returns a promise when the view (Map or Scene ) 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. |
arcgis | Framework | View-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. |
arcgis | Any | All components, except view-based components | Event 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.) |
component | Any | All 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
reactive
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.
reactive
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 when
.
reactive
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 get
function.
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 reactive
in action, you can explore these samples: