Legend Widget with GroupLayers

2487
10
Jump to solution
12-05-2017 06:18 AM
JamesS1
Occasional Contributor

When using group layers, the legend widget uses the group layer name as the name of all the group's children layers.

0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Emeritus

James,

   It is actually very simple to fix that too. Just omit the "title" property from the layerInfos.

        var legend = new Legend({
          view: view,
          layerInfos: [{
            layer: demographicGroupLayer
          }]
        });

Don't forget to mark this question as answered by clicking on the "Mark Correct" link on the reply that answered your question.

View solution in original post

0 Kudos
10 Replies
JamesS1
Occasional Contributor

Has no one else experienced this? I am using feature layers (not a web map).

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

James,

You say 

When using group layers

Then you say

 I am using feature layers

How are you using Group Layers and feature layers?...

FeatureLayer only supports on layer of a map service.

0 Kudos
JamesS1
Occasional Contributor

The FeatureLayer is a sub layer for the GroupLayer. I have a few group layers and each group layer has a few feature layer sub layers. The layers property on GroupLayer is where these feature layers go. This works perfect with the LayerList widget (all namings are correct, including the sub layers). With the Legend widget, the group layer name is correct, but all sub layers, instead of using the feature layer "title", use the group layer "title".

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

James when I add the legend portion of the Legend widget sample to the widgets layerlist actions sample I do not see that issue at all:

<!DOCTYPE html>
<html>
<head>

  <meta charset="utf-8">
  <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">

  <title>LayerList widget with actions - 4.5</title>

  <style>
    html,
    body,
    #viewDiv {
      padding: 0;
      margin: 0;
      height: 100%;
      width: 100%;
      overflow: hidden;
    }
  </style>

  <link rel="stylesheet" href="https://js.arcgis.com/4.5/esri/css/main.css">
  <script src="https://js.arcgis.com/4.5/"></script>

  <script>
    require([
      "esri/Map",
      "esri/views/MapView",
      "esri/layers/GroupLayer",
      "esri/layers/MapImageLayer",
      "esri/widgets/LayerList",
      "esri/widgets/Legend",
      "dojo/domReady!"
    ], function(
      Map, MapView, GroupLayer, MapImageLayer, LayerList, Legend
    ) {

      // Create layer showing household income.

      var householdIncomeLayer = new MapImageLayer({
        url: "https://server.arcgisonline.com/arcgis/rest/services/Demographics/USA_Median_Household_Income/MapSer...",
        title: "US Median Household Income"
      });

      // Create layer showing median net worth.
      // Set visibility to false so it's not visible on startup.

      var medianNetWorthLayer = new MapImageLayer({
        url: "https://server.arcgisonline.com/arcgis/rest/services/Demographics/USA_Median_Net_Worth/MapServer",
        title: "US Median Net Worth",
        visible: false
      });

      // Create GroupLayer with the two MapImageLayers created above
      // as children layers.

      var demographicGroupLayer = new GroupLayer({
        title: "US Demographics",
        visible: true,
        visibilityMode: "exclusive",
        layers: [householdIncomeLayer, medianNetWorthLayer],
        opacity: 0.75
      });

      // Create a map and add the group layer to it

      var map = new Map({
        basemap: "dark-gray",
        layers: [demographicGroupLayer]
      });

      // Add the map to a MapView

      var view = new MapView({
        center: [-98.5795, 39.8282],
        zoom: 5,
        container: "viewDiv",
        map: map
      });

      // Creates actions in the LayerList.

      function defineActions(event) {

        // The event object contains an item property.
        // is is a ListItem referencing the associated layer
        // and other properties. You can control the visibility of the
        // item, its title, and actions using this object.

        var item = event.item;

        if (item.title === "US Demographics") {

          // An array of objects defining actions to place in the LayerList.
          // By making this array two-dimensional, you can separate similar
          // actions into separate groups with a breaking line.

          item.actionsSections = [
            [{
              title: "Go to full extent",
              className: "esri-icon-zoom-out-fixed",
              id: "full-extent"
            }, {
              title: "Layer information",
              className: "esri-icon-description",
              id: "information"
            }],
            [{
              title: "Increase opacity",
              className: "esri-icon-up",
              id: "increase-opacity"
            }, {
              title: "Decrease opacity",
              className: "esri-icon-down",
              id: "decrease-opacity"
            }]
          ];
        }
      }

      view.then(function() {

        // Create the LayerList widget with the associated actions
        // and add it to the top-right corner of the view.

        var layerList = new LayerList({
          view: view,
          // executes for each ListItem in the LayerList
          listItemCreatedFunction: defineActions
        });

        // Event listener that fires each time an action is triggered

        layerList.on("trigger-action", function(event) {

          // The layer visible in the view at the time of the trigger.
          var visibleLayer = householdIncomeLayer.visible ?
            householdIncomeLayer : medianNetWorthLayer;

          // Capture the action id.
          var id = event.action.id;

          if (id === "full-extent") {

            // if the full-extent action is triggered then navigate
            // to the full extent of the visible layer
            view.goTo(visibleLayer.fullExtent);

          } else if (id === "information") {

            // if the information action is triggered, then
            // open the item details page of the service layer
            window.open(visibleLayer.url);

          } else if (id === "increase-opacity") {

            // if the increase-opacity action is triggered, then
            // increase the opacity of the GroupLayer by 0.25

            if (demographicGroupLayer.opacity < 1) {
              demographicGroupLayer.opacity += 0.25;
            }
          } else if (id === "decrease-opacity") {

            // if the decrease-opacity action is triggered, then
            // decrease the opacity of the GroupLayer by 0.25

            if (demographicGroupLayer.opacity > 0) {
              demographicGroupLayer.opacity -= 0.25;
            }
          }
        });

        // Add widget to the top right corner of the view
        view.ui.add(layerList, "top-right");
        
        var legend = new Legend({
            view: view
          });

          // Add widget to the bottom right corner of the view
          view.ui.add(legend, "bottom-right");
      });
    });
  </script>

</head>

<body>
  <div id="viewDiv"></div>
</body>

</html>
0 Kudos
JamesS1
Occasional Contributor

Did you try it with feature layers? I'm not setting the layers [] property directly in the GroupLayer. I am using grpLyr.add(featLyr).

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

James,

  Yep, it must be something in your code. Here is a sample using FeatureLayers and grouplayer.add:

<!DOCTYPE html>
<html>
<head>

  <meta charset="utf-8">
  <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">

  <title>LayerList widget with actions - 4.5</title>

  <style>
    html,
    body,
    #viewDiv {
      padding: 0;
      margin: 0;
      height: 100%;
      width: 100%;
      overflow: hidden;
    }
  </style>

  <link rel="stylesheet" href="https://js.arcgis.com/4.5/esri/css/main.css">
  <script src="https://js.arcgis.com/4.5/"></script>

  <script>
    require([
      "esri/Map",
      "esri/views/MapView",
      "esri/layers/GroupLayer",
      "esri/layers/FeatureLayer",
      "esri/widgets/LayerList",
      "esri/widgets/Legend",
      "dojo/domReady!"
    ], function(
      Map, MapView, GroupLayer, FeatureLayer, LayerList, Legend
    ) {

      // Create layer showing household income.

      var householdIncomeLayer = new FeatureLayer({
        url: "https://server.arcgisonline.com/arcgis/rest/services/Demographics/USA_Median_Household_Income/MapSer...",
        title: "US Median Household Income Counties"
      });

      // Create layer showing median net worth.
      // Set visibility to false so it's not visible on startup.

      var medianNetWorthLayer = new FeatureLayer({
        url: "https://server.arcgisonline.com/arcgis/rest/services/Demographics/USA_Median_Net_Worth/MapServer/3",
        title: "US Median Net Worth Counties",
        visible: false
      });

      // Create GroupLayer with the two MapImageLayers created above
      // as children layers.

      var demographicGroupLayer = new GroupLayer({
        title: "US Demographics",
        visible: true,
        visibilityMode: "exclusive",
        //layers: [householdIncomeLayer, medianNetWorthLayer],
        opacity: 0.75
      });
      demographicGroupLayer.add(medianNetWorthLayer);
      demographicGroupLayer.add(householdIncomeLayer);

      // Create a map and add the group layer to it

      var map = new Map({
        basemap: "dark-gray",
        layers: [demographicGroupLayer]
      });

      // Add the map to a MapView

      var view = new MapView({
        center: [-98.5795, 39.8282],
        zoom: 5,
        container: "viewDiv",
        map: map
      });

      view.then(function() {

        // Create the LayerList widget with the associated actions
        // and add it to the top-right corner of the view.

        var layerList = new LayerList({
          view: view
        });

        // Add widget to the top right corner of the view
        view.ui.add(layerList, "top-right");

        var legend = new Legend({
            view: view
          });

          // Add widget to the bottom right corner of the view
          view.ui.add(legend, "bottom-right");
      });
    });
  </script>

</head>

<body>
  <div id="viewDiv"></div>
</body>

</html>
0 Kudos
JamesS1
Occasional Contributor

After looking at your sample, I found the issue. I am setting the layerInfos property for the Legend widget. Once removed, the legend works fine with the group layers. Since I want to show all map layers in the legend, this is not an issue for me (removing the layerInfos property). However, if I only wanted to show a subset of layers by specifying layerInfos, then the legend widget has issues with GroupLayers.

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

James,

   It is actually very simple to fix that too. Just omit the "title" property from the layerInfos.

        var legend = new Legend({
          view: view,
          layerInfos: [{
            layer: demographicGroupLayer
          }]
        });

Don't forget to mark this question as answered by clicking on the "Mark Correct" link on the reply that answered your question.

0 Kudos
JamesS1
Occasional Contributor

I'll mark as answered, but it is painful dealing with some of these things. How would one know to remove the title property?

0 Kudos