Select to view content in your preferred language

ArcGISDynamicMapServiceLayer's setVisibleLayers not working for me

3821
4
Jump to solution
12-03-2012 11:41 AM
JoanneMcGraw
Frequent Contributor
I think there is some basic principle to the ArcGISDynamicMapServiceLayer's setVisibleLayers functionality that I am not undersanding and I'm hoping someone can tell me what I'm missing.  Certainly, any of the forum posts I've found suggest that it works as I expect but I can't seem to affect the display of my map as I wish.

I have created the example below to illustrate what I am trying to do in my application with my own data. Here, I am using servicesbeta1.esri.com's Water_Network service and setting the visible layers for the service to "MidScale" (19) and "Water Mains - Block View" (23). However, when I load the page, the map is also showing "Water Network Structures - City View" (layer 20). The circle with the letter 'T' is from that layer; and, as far as I am concerned, should not be displayed in the map given the setVisibleLayers([19,23]) call I am making.

Can anyone tell me what I am missing here? Is there something else I'm supposed to do besides just pass an array identifying the visible layers I want shown?

Cheers,
jtm

<html>   <head>     <title>setVisibleLayers Question</title>     <link rel="stylesheet" type="text/css" href="http://serverapi.arcgisonline.com/jsapi/arcgis/3.2/js/dojo/dijit/themes/claro/claro.css">     <link rel="stylesheet" type="text/css" href="http://serverapi.arcgisonline.com/jsapi/arcgis/3.2/js/esri/css/esri.css" />     <script type="text/javascript" src="http://serverapi.arcgisonline.com/jsapi/arcgis/?v=3.2"></script>  <script type="text/javascript"> dojo.require("esri.map");  function init() {     var extent = new esri.geometry.Extent(         {             "xmin":1016752.0585392233,"ymin":1857876.6670321897,"xmax":1051557.2503922875,"ymax":1876696.1114766342             ,"spatialReference":{                 "wkt": "PROJCS[\"NAD_1983_HARN_StatePlane_Illinois_East_FIPS_1201\",GEOGCS[\"GCS_North_American_1983_HARN\",DATUM[\"D_North_American_1983_HARN\",SPHEROID[\"GRS_1980\",6378137.0,298.257222101]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"False_Easting\",984250.0],PARAMETER[\"False_Northing\",0.0],PARAMETER[\"Central_Meridian\",-88.33333333333333],PARAMETER[\"Scale_Factor\",0.999975],PARAMETER[\"Latitude_Of_Origin\",36.66666666666666],UNIT[\"Foot_US\",0.3048006096012192]]"             }         }     );      var map = new esri.Map("map",{extent: extent});      var service = new esri.layers.ArcGISDynamicMapServiceLayer("http://servicesbeta2.esri.com/arcgis/rest/services/Water_Network/MapServer");      // I've tried setting the visibleLayers before and after adding the ArcGISDynamicMapServiceLayer to the map     // Here, I also tried the optional "false" to refresh, even though I hadn't added it to the map yet      //service.setVisibleLayers([19,23]);      map.addLayer(service);      service.setVisibleLayers([19,23], false); } dojo.addOnLoad(init); </script>   </head>   <body>     <div id="map" class="claro" style="width:1130px; height:611px; border:1px solid #000;"></div>   </body> </html>
0 Kudos
1 Solution

Accepted Solutions
ReneRubalcava
Esri Frequent Contributor
Looking at the Layer list, index 19 is a group layer and 23 is a member of that group.
http://servicesbeta2.esri.com/arcgis/rest/services/Water_Network/MapServer

So by specifying service.setVisibleLayers([19,23]), you are asking for the whole group of layers. Index 19 will take precedence over the individual layer of 23.

If you omit index 19 and only use service.setVisibleLayers([23]), I think you get your desired result.

Just remember when you specify the index of a group layer, you are bringing all layers in that group.

Hope that helps a bit.

View solution in original post

0 Kudos
4 Replies
ReneRubalcava
Esri Frequent Contributor
Looking at the Layer list, index 19 is a group layer and 23 is a member of that group.
http://servicesbeta2.esri.com/arcgis/rest/services/Water_Network/MapServer

So by specifying service.setVisibleLayers([19,23]), you are asking for the whole group of layers. Index 19 will take precedence over the individual layer of 23.

If you omit index 19 and only use service.setVisibleLayers([23]), I think you get your desired result.

Just remember when you specify the index of a group layer, you are bringing all layers in that group.

Hope that helps a bit.
0 Kudos
JoanneMcGraw
Frequent Contributor
Odoe,

Thank you for your response.

Indeed:
when you specify the index of a group layer, you are bringing all layers in that group
was that basic principle I was not getting.

Do you have any idea why ESRI would implement the JSAPI to interpret the checkbox status of a group differently than it does in ArcMap and on ArcGIS Online? In those environments, the group must be turned on in order to see the layers that are turned on below it but it doesn't automatically display them all even if they are unchecked. It seems odd that they would go to the lengths of coding ArcGIS Online to replicate the functionality in ArcMap, but not introduce that interpretation of visibleLayers to the JSAPI.

Perhaps this question is better directed to someone involved in the development of the JSAPI...but, I'm wondering, is it just me that finds this odd?

Cheers,
jtm
0 Kudos
JeffPace
MVP Alum
I agree.  However i think it is likely due to a code driven focus.  I.e. if group options were respected, If i set layer12 visible, , it might do nothing if i forget to check if layer 9 (the group) is also visible.

The logic gets really complicated if its

1. Check if group is on
2, If group not on turn on
3. Check if other layers in group already on but hidden by group
4. Deal with those layers
5. turn desired layer on.

We, to simplify, just refuse to group layers in mxds that are destined for server.
0 Kudos
JoanneMcGraw
Frequent Contributor
Unfortunately, the code is complicated whether they write it or I do. As it is, given odoe's answer above, I implemented what you describe in my application yesterday. It just seems to me that the ESRI developers have already come across this in their own development of the ArcGIS Online interface and resolved to replicate the TOC functionality of ArcMap there. Likely their reasons for doing so will apply to others (as it did to me) and they will wish to do the same. Rather than many people needing to figure out the algorithm to support it themselves, the visibleLayers implementation could just handle it.

By now, however, people have coded with visibleLayers as it is, so changing it would be problematic. A better solution, at this point, would likely be the inclusion of a TOC dijit to the JSAPI. They already have the code in ArcGIS Online...

And, although it's questionable how useful this will be to anyone, since our GUI library is ExtJs rather than Dojo, I'll include the relevant code here as reference to anyone who's interested.

Cheers,
jtm

    :
    
initComponent: function(){
    this.panel = Ext.create(
        "Ext.tree.Panel"
        ,{
            store: this.parentTreeStore
            ,rootVisible: false
            ,hideHeaders: true
                :
        }
    );
    this.panel.on("checkchange", this.treeOnCheckChange, this);
    this.add(this.panel);
}

,treeOnCheckChange: function(node, checked, eOpts){
    var service = this.getService(node);

    // if it is the service itself that is turned on/off
    // simply set its visibility as requested
    if (node.raw.service === service){
        service.setVisibility(checked);
        return;
    }

    // if any group above the node is turned off, there
    // will be no change to the service's visibleLayers
    var tmpNode = node.parentNode;
    while (!tmpNode.parentNode.isRoot()){
        if (tmpNode.get("checked") === false){
            return;
        }
        tmpNode = tmpNode.parentNode;
    }

    var visibleLayers = this.getVisibleLayersFromTree(node);

    if (checked){ // adding to the visibleLayers
        visibleLayers.push.apply(visibleLayers, service.visibleLayers);
    }
    else { // removing from the visibleLayers
        // it's already been checked off in the tree so wasn't
        // returned in the getVisibleLayersFromTree call above
        visibleLayers.push(node.raw.id);

        var tmpVisibleLayers = [];
        for (var i = 0; i < service.visibleLayers.length; ++i){
            if (visibleLayers.indexOf(service.visibleLayers) === -1){
                tmpVisibleLayers.push(service.visibleLayers);
            }
        }

        visibleLayers = tmpVisibleLayers;
    }

    var pos = visibleLayers.indexOf(-1);
    if (pos != -1){ // if all layers were turned off previously, this item is still there
        visibleLayers.splice(pos, 1);
    }

    if (visibleLayers.length === 0){
        visibleLayers.push(-1);
    }

    service.setVisibleLayers(visibleLayers);
}

// the parentTreeStore can contain multiple treeStores, each associated with a single 
// mapping service. The tree's root is just a container for those service children
// and the service layer itself is attached to its uppermost node
,getService: function(child){
    var parent = child.parentNode;
    while(!parent.isRoot()){
        child = parent;
        parent = child.parentNode;
    }
    return child.raw.service;
}

,getVisibleLayersFromTree: function(node){
    var results = [];
    if (node.isLeaf()){
        if (node.get("checked")){
            results.push(node.raw.id);
        }
    }
    else {
        for (var i = 0; i < node.childNodes.length; i++){
            var visibleLayers = this.getVisibleLayersFromTree(node.childNodes);
            if (visibleLayers.length > 0){
                results.push.apply(results, visibleLayers);
            }
        }
    }
    return results;
}
        :
0 Kudos