8.8 Map Components
8.8 Map Components jed124Paralleling their Calcite development, Esri has made a strong push to produce map-centric web components with the goal of simplifying the app development experience for 3rd-party developers.
In this section of the lesson, we’ll dive into Esri’s map components, looking at their basic implementation, their documentation, how to combine them with objects from the Core API we’ve been dealing with thus far in the course, and finally looking specifically at the components that replace the deprecated widgets covered earlier in this lesson.
8.8.1 Intro to Map Components
8.8.1 Intro to Map Components jed124Some background on web components technology can be found on Mozilla Developer. (Read as far as you like, but focus on the brief Concepts and Usage section at the top of the article. Also note that we won't be creating web components as outlined by the 5 steps at the end of that section. We'll just be consuming components created by Esri.)
Let's begin by examining a sample from Esri's Maps SDK for JS documentation.
- Go to the Sample Code area of the documentation, find the Intro to map components (2D) sample under the Get Started heading, and have a look at the code in the sandbox or CodePen.
Note that a map is added to the page through the use of a custom arcgis-map element. No need to instantiate separate Map and MapView objects as required when working strictly with the Core API. Initial map settings (basemap, zoom, and center) are applied as attributes on the HTML element. - Adjust the zoom and center attributes to focus the map on your area of interest.
Add zoom and home buttons to the UI using the Zoom and Home components:
<arcgis-map basemap="topo-vector" zoom="4" center="15, 65"> <arcgis-zoom position="top-left"></arcgis-zoom> <arcgis-home position="top-left"></arcgis-home> </arcgis-map>If you’d like to use the Map component to display a web map saved in ArcGIS Online, making that happen is as simple as setting its item-id attribute.
Go into AGO, find your Jen and Barry’s web map from Lesson 1, copy its portal item ID, and use it to set the map's item-id. Your web map will carry a basemap setting with it, so while setting the item-id attribute, you can also remove the basemap attribute:
<arcgis-map
basemap="topo-vector"item-id="<your web map id here>" zoom="6" center="-78, 42">
Awesome, huh? You're probably wondering why we didn't talk about this sooner. It's possible that as the course evolves, we'll shift the discussion of map components toward the beginning. These coarse-grained elements can really make it easy to put together relatively simple apps. However, if your app has much complexity to it, you're going to have to work with the finer-grained objects from the Core API. The two parts of the SDK are not mutually exclusive, and we'll momentarily how to build an app that utilizes both map components and objects from the Core API.
Before we do that, here are a few important points to note in this map component sample:
- You should add references to the Maps SDK for JS in the head of the HTML document, just as we've been doing.
The map components must be referenced separately (also in the head):
<script type="module" src="https://js.arcgis.com/4.33/map-components"></script>
- In the body of the doc, you no longer need a div that will serve as the container for a Core API Map object. The arcgis-map element will serve that purpose now. (If you want a 3D map instead, you can use arcgis-scene rather than arcgis-map.)
- JavaScript code that builds upon the components should go in a script element in the page body as opposed to the head.
8.8.2 Integration with the Core API
8.8.2 Integration with the Core API jed124Map components can simplify the basics of app development, but at some point you’re likely to need the more fine-grained objects made available through the Core API we’ve been working with during the class. The Intro to map components (2D) sample provides a crosswalk of sorts for connecting map component code with Core API code. The first step is to obtain a reference to the Map’s DOM element:
const viewElement = document.querySelector("arcgis-map");
From there, you can set up a listener for when the Map is ready for interaction:
viewElement.addEventListener("arcgisViewReadyChange", (event) => {
console.log("Map component is ready", event);
});
Any code you want to build upon the map components can be embedded within this anonymous event listener.
Picking up where we left off, let’s add Penn State buildings (which we worked with in Lesson 1) to the map as a FeatureLayer. The first step will be to import that module.
- Add the following to the top of the script element that holds your JS code:
const [FeatureLayer] = await $arcgis.import( ["@arcgis/core/layers/FeatureLayer.js"] ); - Within the listener for the “arcgisViewReadyChange” event, instantiate a new FeatureLayer:
const buildingsLyr = new FeatureLayer({ url: "https://mapservices.pasda.psu.edu/server/rest/services/pasda/PSU_Campus/MapServer/1" });Creation of this FeatureLayer could also happen before getting the reference to the Map component. -
Finally, add the FeatureLayer to the map:
viewElement.map.add(buildingsLyr);
Note that while the arcgis-map element is referred to as a Map component, adding one to your page actually creates a MapView from the Core API. Thus, to add a layer, you need to access the Map associated with the MapView through its map property (viewElement.map). In this last step, you could certainly store a reference to the Map instead of chaining:
const map = viewElement.map;
map.add(buildingsLyr);
Finally, a side note on $arcgis.import()… We’ve implemented this function with arrays of modules/variables, but you should be aware that it can also be implemented without arrays. For example, in this little walkthrough in which FeatureLayer is the only Core API module being imported, we could do the import as follows instead:
const FeatureLayer = await $arcgis.import("@arcgis/core/layers/FeatureLayer.js");
You'll see single modules imported in this way in the documentation and I didn’t want the different syntax to throw you off.
8.8.3 Map Component Documentation
8.8.3 Map Component Documentation jed124The documentation of the SDK's map components can be accessed by going to the documentation home page (https://developers.arcgis.com/javascript/latest/), clicking on the References tab, and then on the Map Components box. Alternatively, if you happen to be looking at a Core API reference page, say MapView's, the Topics pane on the left side of the window will have its tree view expanded to show the core node. If you scroll up to the top of the tree view and collapse the core node, you'll see that there are a few other nodes in the tree, all component-related, with map-components being one of them. You can expand the map-components node to access a list of available components.
Click on the Map component to access its documentation. The top of its page will look similar to a Core API class page, with info on how to import the component depending on whether you're accessing the SDK via ESM or CDN. One nice aspect of map components, as shown on the Map component page, is that you don't need to import a separate module for each component the way that you must with Core API classes. You just need to include the single reference to the map components library in your HTML doc's head and you're set to use any map component:
<script type="module" src="https://js.arcgis.com/4.33/map-components/"></script>
Much like a Core API class page, a map component page will include a section detailing its Properties, Methods, and Events. It will also have a section on the component's Slots (which were discussed in the Calcite part of the lesson).
The unique part of the component pages is the Demo section, which provides a mini-sandbox for seeing how the component works. A live preview appears on the left, while a set of controls/properties/attributes appears on the right. The control default values can be modified and the preview will update accordingly.
The Map component demo shows a web map of NFL stadiums by default through the setting of the item-id control. Wipe out that ID (the component will go blank), then assign a basemap setting of satellite (or any other valid basemap you wish). Feel free to assign values to other controls, such as zoom or center. (The center control requires a value in a form like -100, 40.)
After you're done experimenting with the controls, click the Code tab along the top of the Demo GUI. You should see the HTML code for the custom element you configured and can click the Copy button to copy the code to your clipboard. Note that the "Control" settings made through the Demo GUI translate to HTML attribute settings. (Interestingly, I'm seeing an item-id attribute without a string assigned to it after doing the customization I just recommended to you. While the inclusion of this unset attribute won't hurt anything, it really makes more sense to just omit it if you're not setting it.)
The Demo GUI offers a number of buttons along the top that you're free to experiment with, though I'm not sure that I'd ever find a use for them myself. There is a Reset controls button near the top of the Controls pane, allowing you to go back to its default settings. You could also simply reload the documentation page altogether.
One last point on the Demo sandbox is that the controls it shows will be the component properties that can be set to simple, scalar values (strings, numbers, and Booleans). If you click on the Properties link to jump down to that section of the component's documentation, you should note that the properties that have something in the Attribute column correspond to the controls available in the Demo sandbox. But you should keep in mind that those properties without something in the Attribute column are ones that you can set using JS code. We'll see an example of doing that in the discussion of the Legend component later in this section.
8.8.4 BasemapToggle component
8.8.4 BasemapToggle component jed124As noted earlier, Esri has deprecated the BasemapToggle widget in favor of the newer component by the same name. The pen below shows the use of this component. Note the setting of the position and next-basemap attributes.
See the Pen L8_BasemapToggle_component by Jim Detwiler (@jimdetwiler) on CodePen.
8.8.5 BasemapGallery component
8.8.5 BasemapGallery component jed124As we saw with the BasemapGallery widget example, in this example a BasemapGallery component is embedded within an Expand component. Note the setting of three attributes on the Expand component. The position attribute is self-explanatory. The mode can be either "floating", as shown here, or "drawer", which causes the basemaps to appear in a box filling much of the bottom of the window. The close-on-esc attribute controls whether the user can close the gallery by pressing the Esc key on the keyboard. As a Boolean attribute, you should simply refer to it by name (i.e., don't say close-on-esc="true") to set the attribute to true or omit it to set it to false.
You can have the gallery displayed when the map loads by setting the Boolean expanded attribute to true.
See the Pen BasemapGallery_component by Jim Detwiler (@jimdetwiler) on CodePen.
8.8.6 LayerList component
8.8.6 LayerList component jed124The LayerList widget (covered earlier in the lesson) is not labeled as deprecated in the SDK documentation (as of Jul 2025). Presumably that means the LayerList component lacks some important functionality. In any case, the example below shows the component embedded within an Expand component, like the BasemapGallery example earlier. One attribute you might consider setting is visibility-appearance, which allows for showing the user checkboxes for toggling layer visibility rather than the default eyeball icon.
See the Pen LayerList_component by Jim Detwiler (@jimdetwiler) on CodePen.
8.8.7 Legend component
8.8.7 Legend component jed124As with the LayerList widget, Esri has not yet deprecated the Legend widget (as of Jul 2025). The example below demonstrates the use of the newer Legend component, which you should use over the widget unless it doesn't deliver some needed behavior.
See the Pen Legend Demo by Jim Detwiler (@jimdetwiler) on CodePen.
Looking at the code, the component has two attributes set: position and legend-style. The latter defaults to "classic", but can be set to "card" instead. The part of the code to pay particular attention to involves customizing the legend to show only the cities layer. As with the Legend widget covered earlier, the Legend component has a layerInfos property that can be used to specify which layers to depict. Looking at the documentation, you should note that there is no layer-infos attribute; this is sensible since it's not possible to specify the information associated with this property using a simple string. So this example is the first to demonstrate how to set a component property using JS as opposed to setting an attribute using HTML. The key is to use the same querySelector() DOM method that we've seen used to get a reference to the view element, but this time to get a reference to the legend element. With a reference to the element (component), its layerInfos property can be set.
8.8.8 ScaleBar component
8.8.8 ScaleBar component jed124The pen below, modeled after the example for the ScaleBar widget, demonstrates the use of the ScaleBar component. Note that the style and unit are conveniently set using HTML attributes.
See the Pen ScaleBar demo - components by Jim Detwiler (@jimdetwiler) on CodePen.
This concludes the demonstration of map components built into Esri's Maps SDK for JS. There are many others and I recommend you take a few minutes to peruse them in the documentation. Some you may find to be of particular interest include (not an exhaustive list):
- Area Measurement
- Distance Measurement
- Bookmarks: typically used to provide access to spatial bookmarks stored with a web map
- Editor
- Feature Table
- Navigation Toggle: for 3D scene navigation
- Swipe