Learn how to construct a UI for a mapping application with web components using Calcite components and ArcGIS Maps SDK for JavaScript's Map components.
You will use Calcite components to enhance the user experience and drive interaction in your mapping application. This tutorial focuses on the user interface and Map components to streamline app creation, and does not require prior knowledge of the ArcGIS Maps SDK for JavaScript. If you are new to the ArcGIS Maps SDK for JavaScript
Prerequisites
Steps
Create a new pen
- Navigate to CodePen to create a new pen for your mapping application.
Add HTML
-
In CodePen > HTML, add HTML and CSS to create a page with an
arcgis-mapcomponent, which will display the mapA map is a collection of layers that are displayed in 2D. It is typically composed of a basemap layer and data layers. . -
Add an
idto thearcgis-mapcomponent to reference throughout app development, add CSS to set it's width and height to the browser's window, and Flexbox to supplement further app styling.
The <! tag is not required in CodePen. If you are using a different editor or running the page on a local server, be sure to add this tag to the top of your HTML page.
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<title>Calcite components: Construct a mapping app with web components</title>
</head>
<style>
html,
body,
#mapEl {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
display: flex;
}
</style>
<body>
<arcgis-map id="mapEl"></arcgis-map>
</body>
<script type="module">
</script>
</html>- In the
<headelement, add the ArcGIS Maps SDK for JavaScript> ArcGIS Maps SDK for JavaScript, previously known as ArcGIS API for JavaScript, is a developer product for building mapping and spatial analysis applications for the web. script reference. Visit build mapping apps to learn more about the single script tag for CDN users.
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<title>Calcite components: Create a mapping app with web components</title>
<script type="module" src="https://js.arcgis.com/5.0/"></script>
</head>
Use an API key
An API key
- Go to the get started with security and authentication to build an app that can access secure resources.
- Back in CodePen >
<script, import the> esriclass.Config - Set the
apiproperty.Key
<script type="module">
const [esriConfig] = await $arcgis.import([
"@arcgis/core/config.js"
]);
esriConfig.apiKey = "YOUR_API_KEY";
</script>Display a map
The map
- In the
<body, you will initialize the> arcgis-mapcomponent using theitem-idattribute, which specifies the webmap'sA web map is a map stored as a JSON object that defines properties such as the basemap layer, data layers, layer styles, and pop-up styles. Its JSON structure is defined by the web map specification. item ID.
<arcgis-map id="mapEl" item-id="03d584a7c9874b44821c6a766c3bbc11">
</arcgis-map>
- Next, add an
arcgis-zoomcomponent and set itsslotwith respect to thearcgis-mapcomponent.
<arcgis-map id="mapEl" item-id="03d584a7c9874b44821c6a766c3bbc11">
<arcgis-zoom slot="top-left"></arcgis-zoom>
</arcgis-map>
At this point the application will display a map
Create the layout
To create the layout you will use calcite-shell, which organizes other components on the page using slots. Slots are a web component concept and there is a brief section in Core concepts. A list of Calcite components slots, if it has any, can be found on its reference page. For example, here are shell's slots.
- Add the
calcite-shellcomponent, and set thecontent-behindattribute so users can interact with the mapA map is a collection of layers that are displayed in 2D. It is typically composed of a basemap layer and data layers. behind the shell.
<calcite-shell content-behind>
<arcgis-map id="mapEl" item-id="03d584a7c9874b44821c6a766c3bbc11">
<arcgis-zoom slot="top-left"></arcgis-zoom>
</arcgis-map>
</calcite-shell>
-
Next, add the
calcite-shell-panelcomponent, placing it in shell's"panel-end"slot. -
Then, set the shell panel's
displayattribute toMode "float"so it's content appears to hover over the mapA map is a collection of layers that are displayed in 2D. It is typically composed of a basemap layer and data layers. .
<calcite-shell content-behind>
<calcite-shell-panel id="shell-panel-nav" slot="panel-end" display-mode="float" height="l">
</calcite-shell-panel>
<arcgis-map id="mapEl" item-id="03d584a7c9874b44821c6a766c3bbc11">
<arcgis-zoom slot="top-left"></arcgis-zoom>
</arcgis-map>
</calcite-shell>
-
Add a
calcite-panelcomponent. Supply anidto dynamically populate theheadingwith the title of the web mapA web map is a map stored as a JSON object that defines properties such as the basemap layer, data layers, layer styles, and pop-up styles. Its JSON structure is defined by the web map specification. , and add thehiddenattribute to hide the component on initialization. -
Then, slot a
calcite-iconinto panel's"header-actions-start"slot. -
Next, slot
calcite-action-barinto panel's"action-bar"slot, where you can addcalcite-actionsto display Map components. -
For each action, add a unique
data-action-idvalue.
<calcite-shell-panel id="shell-panel-nav" slot="panel-end" display-mode="float" height="l">
<calcite-panel id="app-heading" hidden>
<calcite-icon id="logo-icon" slot="header-actions-start" icon="explore" text-label="explore"></calcite-icon>
<calcite-action-bar id="map-actions" slot="action-bar" layout="horizontal" expand-disabled>
<calcite-action icon="layers" text="Layers" data-action-id="layers"></calcite-action>
<calcite-action icon="basemap" text="Basemaps" data-action-id="basemaps"></calcite-action>
<calcite-action icon="legend" text="Legend" data-action-id="legend"></calcite-action>
<calcite-action icon="bookmark" text="Bookmarks" data-action-id="bookmarks"></calcite-action>
<calcite-action icon="print" text="Print" data-action-id="print"></calcite-action>
<calcite-action icon="information" text="About" data-action-id="information"></calcite-action>
</calcite-action-bar>
</calcite-panel>
</calcite-shell-panel>
Add Map components
To build on your layout, you will add Map components that display when a user interacts with a calcite-action.
-
First, add a
calcite-blockcomponent.- Add the
expandedattribute to display its contents - Supply a unique
heading - Provide the value from the corresponding
data-action-idto the block'sdata-block-idattribute - Add the
hiddenattribute so the component and its contents are not displayed when the app is initialized
- Add the
-
In the
calcite-block, slot thearcgis-layer-listMap component.- Set the
reference-elementto the map component'sid
- Set the
<calcite-shell-panel id="shell-panel-nav" slot="panel-end" display-mode="float" height="l">
<calcite-panel id="app-heading" hidden>
<calcite-icon id="logo-icon" slot="header-actions-start" icon="explore" text-label="explore"></calcite-icon>
<calcite-action-bar id="map-actions" slot="action-bar" layout="horizontal" expand-disabled>
<calcite-action icon="layers" text="Layers" data-action-id="layers"></calcite-action>
<calcite-action icon="basemap" text="Basemaps" data-action-id="basemaps"></calcite-action>
<calcite-action icon="legend" text="Legend" data-action-id="legend"></calcite-action>
<calcite-action icon="bookmark" text="Bookmarks" data-action-id="bookmarks"></calcite-action>
<calcite-action icon="print" text="Print" data-action-id="print"></calcite-action>
<calcite-action icon="information" text="About" data-action-id="information"></calcite-action>
</calcite-action-bar>
</calcite-panel>
<!-- Map-specific blocks containing ArcGIS Maps SDK for JavaScript components -->
<calcite-block expanded heading="Layers" data-block-id="layers" hidden>
<arcgis-layer-list drag-enabled reference-element="mapEl" visibility-appearance="checkbox"></arcgis-layer-list>
</calcite-block>
</calcite-shell-panel>
- Repeat steps 1 and 2 to add
calcite-blockcomponents to contain thearcgis-basemap-gallery,arcgis-legend,arcgis-bookmarks, andarcgis-printcomponents.
<!-- Map-specific blocks containing ArcGIS Maps SDK for JavaScript components -->
<calcite-block expanded heading="Layers" data-block-id="layers" hidden>
<arcgis-layer-list drag-enabled reference-element="mapEl" visibility-appearance="checkbox"></arcgis-layer-list>
</calcite-block>
<calcite-block expanded heading="Basemaps" data-block-id="basemaps" hidden>
<arcgis-basemap-gallery reference-element="mapEl"></arcgis-basemap-gallery>
</calcite-block>
<calcite-block expanded heading="Legend" data-block-id="legend" hidden>
<arcgis-legend legend-style="classic" reference-element="mapEl"></arcgis-legend>
</calcite-block>
<calcite-block expanded heading="Bookmarks" data-block-id="bookmarks" hidden>
<arcgis-bookmarks editing-enabled="false" reference-element="mapEl"></arcgis-bookmarks>
</calcite-block>
<calcite-block expanded heading="Print" data-block-id="print" hidden>
<arcgis-print allowed-formats="all" allowed-layouts="all" include-default-templates="false"
reference-element="mapEl"></arcgis-print>
</calcite-block>
Create an information card
An information card can provide users with information about the app's data. You will use calcite-card to display the webmap's
-
Similar to the other Map components, add a
calcite-blockcomponent.- Add the
expandedattribute to display its contents - Supply a unique
heading - Provide the value from the corresponding
data-action-idto the block'sdata-block-idattribute - Add the
closedattribute so the component and its contents are not displayed when the app is initialized
- Add the
-
Add the
calcite-cardcomponent. -
Add the following child elements to the card, with unique
id's:- Define an
imgin the card's"thumbnail"slot - Add three
divelements, one in the"heading"slot, another in the"description"slot, and finally one in the"footer-end"slot
- Define an
<!-- Info block (populates with info from the web map) -->
<calcite-block expanded heading="About the data" data-block-id="information" hidden>
<calcite-card id="card-content">
<img id="card-thumbnail" alt="Webmap thumbnail" slot="thumbnail" />
<div id="card-heading" slot="heading">
<!-- Dynamically populated -->
</div>
<div id="card-description" slot="description">
<!-- Dynamically populated -->
</div>
<div id="card-tags" slot="footer-end">
<!-- Dynamically populated -->
</div>
</calcite-card>
</calcite-block>
Populate the content
You finished adding components to your application! Now populate the panel's heading and information card with content from the web map
- Declare the
arcgis-mapcomponent in the<scripttag.>
<script type="module">
const mapEl = document.getElementById("mapEl");
</script>
-
On the map's
arcgisevent, declare constants for the followingView Ready Change portal's to populate contents from the web mapItem A web map is a map stored as a JSON object that defines properties such as the basemap layer, data layers, layer styles, and pop-up styles. Its JSON structure is defined by the web map specification. :title,thumbnail,Url snippet,modified, andtags. -
Next, add the values to the UI, where:
titlewill supply the panel'sheadingand card's"heading"slotthumbnailadds the card'sUrl img'ssrcproperty to the"thumbnail"slotsnippetandmodifiedsupplement card's"description"slottagswill iterate through each tag to create individualcalcite-chipcomponents in card's"footer-end"slot
mapEl.addEventListener("arcgisViewReadyChange", () => {
const { title, thumbnailUrl, snippet, modified, tags } = mapEl.map.portalItem;
document.getElementById("app-heading").heading = `${title} Explorer`;
document.getElementById("card-heading").innerHTML = title;
document.getElementById("card-thumbnail").src = thumbnailUrl;
document.getElementById("card-description").innerHTML = `<p>${snippet}</p><p>Last modified on ${modified}.</p>`;
tags.forEach(tag => {
document.getElementById("card-tags").innerHTML += `<calcite-chip>${tag}</calcite-chip>`;
});
});
Make components interactive
The next step is to display the calcite-block components, which contain the Map components, when clicking on the corresponding calcite-action components.
- Create a function that will execute when each
calcite-actionis clicked. The function will hide the activecalcite-blockand display the block corresponding to the clicked action. If the user clicks on the active action, the corresponding block will close and there will not be any expanded blocks.
This step uses attribute selectors to access the action and block elements using the data attributes you added above. The values of the data attributes are the names of the corresponding Map component.
- Create a click event listener on the
calcite-action-barusing the function above as the callback.
let activeWidget;
const handleActionBarClick = ({ target }) => {
if (target.tagName !== "CALCITE-ACTION") {
return;
}
if (activeWidget) {
document.querySelector(`[data-action-id=${activeWidget}]`).active = false;
document.querySelector(`[data-block-id=${activeWidget}]`).hidden = true;
}
const nextWidget = target.dataset.actionId;
if (nextWidget !== activeWidget) {
document.querySelector(`[data-action-id=${nextWidget}]`).active = true;
document.querySelector(`[data-block-id=${nextWidget}]`).hidden = false;
activeWidget = nextWidget;
} else {
activeWidget = null;
}
};
document.querySelector("calcite-action-bar").addEventListener("click", handleActionBarClick);
Add a loader component
Now everything is interactive in your application! You can open and close Map components using Calcite components. However, the application takes a second to load, which should be communicated to the user.
- In the
<bodyelement after the shell's closing tag, add a> calcite-loaderto display the component.
</calcite-shell>
<calcite-loader></calcite-loader>- Inside of the
arcgisevent, below the rest of the JavaScript code, hide theView Ready Change calcite-loadercomponent with thehiddenproperty set totrueand display thecalcite-panel. When the map and its properties have loaded into the app, the loader will be hidden and the panel will display in the UI.
mapEl.addEventListener("arcgisViewReadyChange", () => {
const { title, thumbnailUrl, snippet, modified, tags } = mapEl.map.portalItem;
document.getElementById("app-heading").heading = `${title} Explorer`;
document.getElementById("card-heading").innerHTML = title;
document.getElementById("card-thumbnail").src = thumbnailUrl;
document.getElementById("card-description").innerHTML = `<p>${snippet}</p><p>Last modified on ${modified}.</p>`;
tags.forEach(tag => {
document.getElementById("card-tags").innerHTML += `<calcite-chip>${tag}</calcite-chip>`;
});
document.getElementById("app-loader").hidden = true;
document.getElementById("app-heading").removeAttribute("hidden");
});
Add styling
In the <style element, add some additional CSS to enhance the user interface for your heading calcite-panel and information calcite-card.
-
Add Flexbox variables to the
calcite-iconslotted into the panel's"header-actions-start"to align the component. -
Next, add styles for the panel to set the width and heights for:
calcite-shell-panelvia the--calcite-shell-panel-min-widthstyle- A media query for
calcite-shell-panelto support smaller devices, such as mobile phones calcite-blockcomponents containing adata-block-idattribute withmax-height
#logo-icon {
align-self: center;
height: auto;
margin-inline-start: 0.5rem;
}
#shell-panel-nav {
--calcite-shell-panel-min-width: 18rem;
}
@media (max-width: 400px) {
#shell-panel-nav {
--calcite-shell-panel-min-width: 80vw;
}
}
calcite-block[data-block-id] {
max-height: 50vh;
overflow-y: auto;
}
- Finally, add styles to
calcite-cardby addingpaddingto the component, updating thefont-sizeusing CSS variables, and wrapping the tags withflex-wrap.
#card-heading {
font-size: var(--calcite-font-size-md);
}
#card-description {
font-size: var(--calcite-font-size);
}
#card-tags {
flex-wrap: wrap;
}
Run the app
In CodePen, run your code to display the application.
The mapcalcite-action-bar. Clicking on the calcite-action components will expand and collapse the calcite-block components, which contain the ArcGIS Maps SDK for JavaScript Map components.