This sample demonstrates how to add a SubtypeGroupLayer to a Map.
The data in this sample comes from an electric utility network dataset to highlight how utility network datasets can take advantage of the SubtypeGroupLayer’s
features.
How it works
The SubtypeGroupLayer automatically creates a sublayer, known as a SubtypeSublayer, from each subtype
in its corresponding feature service. The purpose of this is to treat each subtype in a feature service as its own layer. By treating
each subtype as its own layer, we can then configure a renderer, popup, and labels for each sublayer.
This sample illustrates a workflow to configure 13 sublayers using LayerList actions. Keep in mind that this data source is a single feature service, so it is fascinating that we will be able to configure 13 sublayers out of a single layer.
First, let us initialize the SubtypeGroupLayer and add it to the Map.
// Create a SubtypeGroupLayer, allowing for richer interaction with each SubtypeSublayer. const subtypeGroupLayer = new SubtypeGroupLayer({ portalItem: { id: "b702d7258a724a53aada3fefc3a36829" }, // new PortalItem() outFields: ["assettype", "assetgroup", "objectid", "transformer_kva", "subnetworkname"], });
viewElement.map.add(subtypeGroupLayer);Note
In order to use the SubtypeGroupLayer, the data source you publish must be published as
a SubtypeGroupLayer. To learn more about how to create a SubtypeGroupLayer using ArcGIS Pro, please
read the following documentation.
Using LayerList actions for SubtypeSublayer property controls
With this sample, we will take advantage of the LayerList actions to add
toggles for labels and renderers for each sublayer. More specifically, we will use the listItemCreatedFunction
property of the LayerList to add toggles for each ListItem in the component. Each ListItem will represent a SubtypeSublayer
displayed on the map. The following function handles configuring the layer properties of a sublayer and adding the UI toggles.
The UI consists of a switch and a radio-button-group for toggling labels and renderers, respectively.
// Configure the controls for each of the LayerList's ListItems. layerList.listItemCreatedFunction = async ({ item }) => { const featureCount = await item.layer.queryFeatureCount(); if (!featureCount) item.layer.listMode = "hide"; if (item.layer === subtypeGroupLayer || !featureCount) return;
const { renderer, title } = item.layer; // Get the layer tied to this ListItem. const layerListItemClone = layerListItemTemplate.content.cloneNode(true); const open = title === "Service Point"; // Open ListItem if its layer title matches.
const content = layerListItemClone.querySelector("calcite-card"); const symbolSwitch = content.querySelector("calcite-switch"); const rendererRadioGroup = content.querySelector("calcite-radio-button-group");
// Add event listeners to the ListItem's controls. symbolSwitch.addEventListener("calciteSwitchChange", () => { handleLabelsChange(symbolSwitch.checked, item); }); rendererRadioGroup.addEventListener("calciteRadioButtonGroupChange", () => { handleRendererChange(rendererRadioGroup.selectedItem, item); });
defaultRenderers[title] = renderer; // Store the layer's original SimpleRenderer. rendererRadioGroup.name = `${title} Renderer`; // Set a unique button group name. item.layer.popupTemplate = popupTemplate; // Set the layer's popup configuration. item.layer.labelingInfo = [labelClass]; // Set the layer's label configuration. item.panel = { content, open, icon: "gear" }; // Assign the ListItem controls.
handleLabelsChange(false, item); // Toggle off feature labels by default. };Updating the Renderer
The code in the sample allows users to toggle between a SimpleRenderer and a UniqueValueRenderer with conditionally triggered VisualVariables.
This highlights how the SubtypeSublayer supports different types of renderers.
const handleRendererChange = async ({ value }, item) => { const { title } = item.layer; const hasVariedAssetTypes = assetGroups[title];
// Use the stored original SimpleRenderer. if (value === "simple") { item.layer.renderer = defaultRenderers[title]; return; }
// Set uniqueValueInfos if asset types are distinguishable. if (hasVariedAssetTypes) { const uniqueValueInfos = createUniqueValueInfos(title); uniqueValueRenderer.uniqueValueInfos = uniqueValueInfos; uniqueValueRenderer.visualVariables = []; item.layer.renderer = uniqueValueRenderer; return; }
// Apply color gradient by object ID if asset types are not distinguishable. const visualVariables = await createVisualVariables({ layer: item.layer, view: viewElement.view, valueExpression: "( $feature.objectid )", theme: "high-to-low", }); uniqueValueRenderer.visualVariables = [visualVariables.color.visualVariable]; item.layer.renderer = uniqueValueRenderer; };Known Limitations
- The
SubtypeGroupLayerdoes not currently support DotDensityRenderer. - Clustering is not currently supported.