Layer List - how to display only root layer group (first level of a tree)

2793
5
Jump to solution
07-01-2016 06:42 AM
MichalGasiorowski
New Contributor III

Hi,

I want to add a service with large number of layers to the LayerList widget.

By default all layers are enabled and the whole tree is expanded:

How to restrain expanding to the first level of the tree?

Alternatively, how to disable the fist level what causes branches to colapse?

0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Emeritus

Michal,

  Sure you can do that through CSS manipulation:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
<title>Layer List Dijit</title>
<link rel="stylesheet" href="https://js.arcgis.com/3.16/dijit/themes/claro/claro.css">
<link rel="stylesheet" href="https://js.arcgis.com/3.16/esri/css/esri.css">

<style>
html, body, .container, #map {
    height:100%;
    width:100%;
    margin:0;
    padding:0;
    margin:0;
    font-family: "Open Sans";
}
#map {
    padding:0;
}
#layerListPane{
    width:25%;
}
.esriLayer{
  background-color: #fff;
}
.esriLayerList .esriList{
    border-top:none;
}
.esriLayerList .esriTitle {
  background-color: #fff;
  border-bottom:none;
}
.esriLayerList .esriList ul{
  background-color: #fff;
}
</style>
<script>var dojoConfig = { parseOnLoad: true };</script>
<script src="https://js.arcgis.com/3.16/"></script>
<script>
require([
    "esri/map",
    "esri/layers/ArcGISDynamicMapServiceLayer",
    "esri/dijit/LayerList",
    "dojo/query",
    "dojo/dom-class",
    "dijit/layout/BorderContainer",
    "dijit/layout/ContentPane",
    "dojo/domReady!"
], function(
    Map,
    ArcGISDynamicMapServiceLayer,
    LayerList,
    query,
    domClass
) {
  var map = new Map("map", {
    basemap: "topo",
    center: [-123, 47],
    zoom: 8,
    sliderStyle: "small"
  });

  var atlasLayer = new ArcGISDynamicMapServiceLayer("http://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer", {
    "id": "atlasLayer",
    "showAttribution": false
  });

  var recreationLayer = new ArcGISDynamicMapServiceLayer("http://sampleserver6.arcgisonline.com/arcgis/rest/services/Recreation/MapServer", {
    "id": "recreationLayer",
    "showAttribution": false
  });

  var waterNetLayer = new ArcGISDynamicMapServiceLayer("http://sampleserver6.arcgisonline.com/arcgis/rest/services/Water_Network/MapServer", {
    "id": "waterNetworkLayer",
    "showAttribution": false
  })

  map.addLayers([atlasLayer, recreationLayer, waterNetLayer]);

  var llWidget = new LayerList({
     map: map,
     layers: [{
       layer: atlasLayer,
        id: "Atlas layers",
        subLayers: true
     },
     {
       layer: recreationLayer,
        id: "Recreation layers",
        subLayers: true
     },
     {
       layer: waterNetLayer,
        id: "Water Network layers",
        subLayers: true
     }], showSubLayers: true, showOpacitySlider: true
  },"layerList");
  llWidget.startup();

  llWidget.on('load', function(){
    expandLayerList();
  });

  function expandLayerList() {
    //This first part will expand the main layers.
    query('.esriLayer').forEach(function(node){
      domClass.add(node, "esriListExpand");
    });
    query('.esriToggleButton').forEach(function(node){
      domClass.replace(node, "esri-icon-down", "esri-icon-right");
    });
    //This part will collapse the sublayer lists
    query('.esriSubListLayer.esriHasSubList.esriSubListExpand.esriListVisible').forEach(function(node){
      console.info(node);
      domClass.remove(node, "esriSubListExpand");
      domClass.remove(node, "esriListVisible");
    });
  }

});
</script>
</head>
<body class="claro">
<div class="container" data-dojo-type="dijit/layout/BorderContainer"
data-dojo-props="design:'headline',gutters:false">
<div id="layerListPane" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'right'">
    <div id="layerList"></div>
</div>
<div id="map" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center'"></div>
</div>
</body>
</html>

View solution in original post

5 Replies
JeffJacobson
Occasional Contributor III
Alternatively, how to disable the fist level what causes branches to colapse?

You can make the layer off by default by setting the visible property in the layer's constructor to false.

If you want the user to NEVER be able to expand the list, you could probably accomplish this with CSS.

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Michal,

  Sure you can do that through CSS manipulation:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
<title>Layer List Dijit</title>
<link rel="stylesheet" href="https://js.arcgis.com/3.16/dijit/themes/claro/claro.css">
<link rel="stylesheet" href="https://js.arcgis.com/3.16/esri/css/esri.css">

<style>
html, body, .container, #map {
    height:100%;
    width:100%;
    margin:0;
    padding:0;
    margin:0;
    font-family: "Open Sans";
}
#map {
    padding:0;
}
#layerListPane{
    width:25%;
}
.esriLayer{
  background-color: #fff;
}
.esriLayerList .esriList{
    border-top:none;
}
.esriLayerList .esriTitle {
  background-color: #fff;
  border-bottom:none;
}
.esriLayerList .esriList ul{
  background-color: #fff;
}
</style>
<script>var dojoConfig = { parseOnLoad: true };</script>
<script src="https://js.arcgis.com/3.16/"></script>
<script>
require([
    "esri/map",
    "esri/layers/ArcGISDynamicMapServiceLayer",
    "esri/dijit/LayerList",
    "dojo/query",
    "dojo/dom-class",
    "dijit/layout/BorderContainer",
    "dijit/layout/ContentPane",
    "dojo/domReady!"
], function(
    Map,
    ArcGISDynamicMapServiceLayer,
    LayerList,
    query,
    domClass
) {
  var map = new Map("map", {
    basemap: "topo",
    center: [-123, 47],
    zoom: 8,
    sliderStyle: "small"
  });

  var atlasLayer = new ArcGISDynamicMapServiceLayer("http://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer", {
    "id": "atlasLayer",
    "showAttribution": false
  });

  var recreationLayer = new ArcGISDynamicMapServiceLayer("http://sampleserver6.arcgisonline.com/arcgis/rest/services/Recreation/MapServer", {
    "id": "recreationLayer",
    "showAttribution": false
  });

  var waterNetLayer = new ArcGISDynamicMapServiceLayer("http://sampleserver6.arcgisonline.com/arcgis/rest/services/Water_Network/MapServer", {
    "id": "waterNetworkLayer",
    "showAttribution": false
  })

  map.addLayers([atlasLayer, recreationLayer, waterNetLayer]);

  var llWidget = new LayerList({
     map: map,
     layers: [{
       layer: atlasLayer,
        id: "Atlas layers",
        subLayers: true
     },
     {
       layer: recreationLayer,
        id: "Recreation layers",
        subLayers: true
     },
     {
       layer: waterNetLayer,
        id: "Water Network layers",
        subLayers: true
     }], showSubLayers: true, showOpacitySlider: true
  },"layerList");
  llWidget.startup();

  llWidget.on('load', function(){
    expandLayerList();
  });

  function expandLayerList() {
    //This first part will expand the main layers.
    query('.esriLayer').forEach(function(node){
      domClass.add(node, "esriListExpand");
    });
    query('.esriToggleButton').forEach(function(node){
      domClass.replace(node, "esri-icon-down", "esri-icon-right");
    });
    //This part will collapse the sublayer lists
    query('.esriSubListLayer.esriHasSubList.esriSubListExpand.esriListVisible').forEach(function(node){
      console.info(node);
      domClass.remove(node, "esriSubListExpand");
      domClass.remove(node, "esriListVisible");
    });
  }

});
</script>
</head>
<body class="claro">
<div class="container" data-dojo-type="dijit/layout/BorderContainer"
data-dojo-props="design:'headline',gutters:false">
<div id="layerListPane" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'right'">
    <div id="layerList"></div>
</div>
<div id="map" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center'"></div>
</div>
</body>
</html>
MichalGasiorowski
New Contributor III

Robert,

Thank you so much for this solution!

This do the trick and is a great starting point for further development.

As I'm beginner in web programming, please let me learn something and decipher your code, not only copy it:)

Please, correct my understanding if necessary and give some light for my (lame) questions.

  1.     query('.esriLayer').forEach(function(node){ 
  2.       domClass.add(node, "esriListExpand"); 
  3.     }); 

Here you search DOM for elements with class '.esriLayer' and for each element (node) found you add an option to expand this node.

How did you know you should use "esriListExpand" here? The only place in documentation where I found it is here: https://developers.arcgis.com/javascript/3/jsapi/css/esri/dijit/LayerList/css/LayerList.css

and there's only one mention:

.esriLayerList .esriListExpand.esriListVisible .esriTabContainer {
  display: block;
}

Why only root level groups of layers are expanded and the rest are colapsed? Isn't '.esriLayer' referencing all layers in the service?

  1.     query('.esriSubListLayer.esriHasSubList.esriSubListExpand.esriListVisible').forEach(function(node){ 
  2.       console.info(node); 
  3.       domClass.remove(node, "esriSubListExpand"); 
  4.       domClass.remove(node, "esriListVisible"); 
  5.     });

Here looking for specific classes and removing some of them. How did you know you should query for 4 classes and remove only 2 of them?

Again, I found only one reference to "esriSuListExpand":

.esriLayerList .esriSubListExpand > .esriSubList {
  display: block;
}

How do you relate it to your code?

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Michal,

  You are not going to find documentation for esri internal workings, so the best way I find is to use my browsers element inspector by right clicking on a dom element and looking at the style tab (in Chrome) and see the classes that are assigned to that element. When the sublayer intially loaded it has these four classes "esriSubListLayer esriHasSubList esriSubListExpand esriListVisible" and when you click on that element it collapses and only has "esriSubListLayer esriHasSubList". So that tells me that "esriSubListExpand esriListVisible" are the classes that cause the sublayer to be expanded.

"esriLayer" class is only assigned to the main layer and "esriSubListLayer" is assigned to sublayer inside the "esriLayer" that should answer your first question.

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

MichalGasiorowski
New Contributor III

Thanks for this explanation. It really shows that being familiar with developer tools is necessary.

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

I didn't forget, just waited for your final reply:)

0 Kudos