Select to view content in your preferred language

Save layer visibility preferences - flex code question

2839
2
Jump to solution
12-18-2013 06:02 AM
RebeccaWatson
Occasional Contributor
Hi,

I am trying to add some functionality to the TOC widget so that users can save which layers they have turned on and reload those settings later. I have had some success but have come up against a problem that I think others have experienced, but I cannot find an answer on the forum and the posts I've seen are quite old.

I seem to be able to save the layer visibility. However, when I come to load this back in I am struggling with group layers.

For example, if I save the layers below:
[ATTACH=CONFIG]29970[/ATTACH]

It reloads like this:
[ATTACH=CONFIG]29971[/ATTACH]

The "pointsInAGroup" features within "aGroup" are actually visible in the map but this is not reflected in the TOC.

Is it possible to force the checkboxes to update correctly?

My two functions that save/load the layer visibility are:

private function saveLayers():void    {     visLayersSO = SharedObject.getLocal("SavedPrefs");     visLayers = new ArrayCollection();          MapUtil.forEachMapLayer(map, function(layer:Layer):void      {      var visLayersList:IList;      if (layer is ArcGISDynamicMapServiceLayer)       {       visLayersList = ArcGISDynamicMapServiceLayer(layer).visibleLayers        var visLayersObj:Object =        {        name: layer.name,        visible: layer.visible,        vislist: visLayersList       }             visLayers.addItem(visLayersObj);      }           });          visLayersSO.data[VISLAYERS] = visLayers;     visLayersSO.flush();     if (visLayersSO.size > 0)     {      Alert.show("Your layers have been saved.")     }    }         private function loadLayers():void    {      visLayersSO = SharedObject.getLocal("SavedPrefs");            if (visLayersSO.size > 0)       {       var visLayers:ArrayCollection = visLayersSO.data[VISLAYERS];              MapUtil.forEachMapLayer(map, function(layer:Layer):void        {                var LayId:int = 0;        for(var i:int=0; i<visLayers.length;i++)                 {         if(visLayers.name == layer.name)         {          LayId = i;          break;         }        }               if (layer is ArcGISDynamicMapServiceLayer)         {         layer.visible = visLayers[LayId].visible;         ArcGISDynamicMapServiceLayer(layer).visibleLayers = visLayers[LayId].vislist;        }               });      }    }
0 Kudos
1 Solution

Accepted Solutions
by Anonymous User
Not applicable
Original User: K0831901

Hi Anthony,

It's been a while but I have finally managed to get to the bottom of this (with a little help from ESRI Ireland - thankyou!) to successfully save which layers are on and off so I thought I would post back the solution I have found. It is not perfect by any means, as it uses layer names to store visibility, so you have to make sure you don't have any repeated layer or group names in your map services (in comparison to using layer IDs, this is still preferable for me because I have to update my services regularly so the ID's change).

I still have two main functions (saveLayers and loadLayers) that run off buttons added to the Layerlist widget, but there are three other functions added. I have commented extensively because, as a beginner, I really appreciate it when people comment a lot.

   import com.esri.viewer.components.toc.tocClasses.TocItem;    import flash.net.SharedObject;     private var visLayersSO:SharedObject;    private const VISLAYERS:String = "vislayers";      private function saveLayers():void    {     //create sharedObject     visLayersSO = SharedObject.getLocal("SavedPrefs");          //Array to store the visibility of the Layers     var layerNodes:Array = new Array();     //Read each node of the TOC     for each (var item:Object in toc.dataProvider)     {      //if the item is a TOC item      if (item is TocItem)           {            //and if it is a group layer            if (TocItem(item).isGroupLayer())             {              //and if the check box is checked              if (TocItem(item).visible == true)               {                //Store the name of the Layer in the array                layerNodes[layerNodes.length] = TocItem(item).label;               }              //Verify the status of the children of this Group Layer              FetchNextVisibleLayer(TocItem(item), layerNodes);             }             else             {        //The Toc Item should be visible              //The item may not have a parent; if it has a parent - it should be a group layer        if (TocItem(item).visible == true && (TocItem(item).parent == null                  || (TocItem(item).visible == true && TocItem(item).parent != null && TocItem(item).parent.isGroupLayer())))               {                //Store the name of the Layer in the array                 layerNodes[layerNodes.length] = TocItem(item).label;               }             }          }      }     //Store this Array in Shared Object     visLayersSO.data[VISLAYERS] = layerNodes;     visLayersSO.flush();          //If there is something in the saved layers then give user a message     if (visLayersSO.size > 0)     {      Alert.show("Your layers have been saved.")     }    }             private function loadLayers():void    {     //get the shared object     visLayersSO = SharedObject.getLocal("SavedPrefs");          //if there is something in the shared object     if (visLayersSO.size > 0)      {      //put the saved info into an array      var layerNodes:Array = visLayersSO.data[VISLAYERS];      var item:Object;      //run through the nodes in the TOC      for each (item in toc.dataProvider)      {       //if the item is a TOC Item       if (item is TocItem)       {        //If the name of the layer is present then it was checked on        if(layerNodes.indexOf(TocItem(item).label) > -1)        {         //Check the Layer Checkbox in the TOC         TocItem(item).visible = true;         }        //Verify the status of this layer's Children        FetchNextLayer(TocItem(item), layerNodes);       }      }     }     //if there is nothing in the shared object tell the user      else      {      Alert.show("You have no saved preferences");      }          //check for unchecked items in the TOC     for each (item in toc.dataProvider)     {      if (item is TocItem)      {       //if the layer's name is not present in the array it was not checked       if(layerNodes.indexOf(TocItem(item).label) == -1)       {        //Uncheck the Group Layer Checkbox         TocItem(item).visible = false;        }       //Go ahead to verify the status of the layer's Children       FetchNextLayerUncheck(TocItem(item), layerNodes);      }     }              }            //If the Layer is visible, store its name in the input array    //and go ahead to verify rest of the nodes      private function FetchNextVisibleLayer(tocItem:TocItem, layerNodes:Array):void      {        //Check each and every node of the input Group Layer     for each (var item:TocItem in tocItem.children)     {         //If it is a group layer      if(item.isGroupLayer())       {       //and it is visible       if (item.visible == true)        {         //store it in the array        layerNodes[layerNodes.length] = item.label;        }       //Since current group layer can have group layers in it,        //keep checking until all the nodes are checked        FetchNextVisibleLayer(item, layerNodes);      }          else          {        //We are checking all nodes but don't want to store the lengend symbology nodes       //so we check if the item is visible and if its parent is a group layer           //A valid layer's parent in this case is a group layer where as a Legend Node's parent is an ordinary layer       if (item.visible == true && item.parent.isGroupLayer())            {              layerNodes[layerNodes.length] = item.label;           }         }         }      }            private function FetchNextLayer(tocItem:TocItem, layerNodes:Array):void    {     //go through the children     for each (var item:TocItem in tocItem.children)     {      //if the name of that layer appears in the layerNodes array      if(layerNodes.indexOf(item.label) > -1)      {       //then set the item's visible property to be true       item.visible = true;      }      //Since a group layer can have group layers, keep checking until all the nodes are checked      FetchNextLayer(item, layerNodes);     }    }            //Uncheck the Layer's checkbox, if the input array doesn't contain the Layer's name     private function FetchNextLayerUncheck(tocItem:TocItem, layerNodes:Array):void    {     for each (var item:TocItem in tocItem.children)     {      //if the name of that layer doesn't appear in the layerNodes array      if(layerNodes.indexOf(item.label) == -1)      {       //set the item's visbile property to be false       item.visible = false;      }      //Since a group layer can have group layers inside, keep checking until all the nodes are checked      FetchNextLayerUncheck(item, layerNodes);     }    }


Hopefully that will help people out a bit. Any suggestions for improvement are welcome.
Thanks

View solution in original post

0 Kudos
2 Replies
AnthonyGiles
Frequent Contributor II
Rebecca,

I have also never worked out a solution to this. I can get the layers to honor their saved visibility but the check boxes act totally independent. If you find a solution please share,

Regards

Anthony
0 Kudos
by Anonymous User
Not applicable
Original User: K0831901

Hi Anthony,

It's been a while but I have finally managed to get to the bottom of this (with a little help from ESRI Ireland - thankyou!) to successfully save which layers are on and off so I thought I would post back the solution I have found. It is not perfect by any means, as it uses layer names to store visibility, so you have to make sure you don't have any repeated layer or group names in your map services (in comparison to using layer IDs, this is still preferable for me because I have to update my services regularly so the ID's change).

I still have two main functions (saveLayers and loadLayers) that run off buttons added to the Layerlist widget, but there are three other functions added. I have commented extensively because, as a beginner, I really appreciate it when people comment a lot.

   import com.esri.viewer.components.toc.tocClasses.TocItem;    import flash.net.SharedObject;     private var visLayersSO:SharedObject;    private const VISLAYERS:String = "vislayers";      private function saveLayers():void    {     //create sharedObject     visLayersSO = SharedObject.getLocal("SavedPrefs");          //Array to store the visibility of the Layers     var layerNodes:Array = new Array();     //Read each node of the TOC     for each (var item:Object in toc.dataProvider)     {      //if the item is a TOC item      if (item is TocItem)           {            //and if it is a group layer            if (TocItem(item).isGroupLayer())             {              //and if the check box is checked              if (TocItem(item).visible == true)               {                //Store the name of the Layer in the array                layerNodes[layerNodes.length] = TocItem(item).label;               }              //Verify the status of the children of this Group Layer              FetchNextVisibleLayer(TocItem(item), layerNodes);             }             else             {        //The Toc Item should be visible              //The item may not have a parent; if it has a parent - it should be a group layer        if (TocItem(item).visible == true && (TocItem(item).parent == null                  || (TocItem(item).visible == true && TocItem(item).parent != null && TocItem(item).parent.isGroupLayer())))               {                //Store the name of the Layer in the array                 layerNodes[layerNodes.length] = TocItem(item).label;               }             }          }      }     //Store this Array in Shared Object     visLayersSO.data[VISLAYERS] = layerNodes;     visLayersSO.flush();          //If there is something in the saved layers then give user a message     if (visLayersSO.size > 0)     {      Alert.show("Your layers have been saved.")     }    }             private function loadLayers():void    {     //get the shared object     visLayersSO = SharedObject.getLocal("SavedPrefs");          //if there is something in the shared object     if (visLayersSO.size > 0)      {      //put the saved info into an array      var layerNodes:Array = visLayersSO.data[VISLAYERS];      var item:Object;      //run through the nodes in the TOC      for each (item in toc.dataProvider)      {       //if the item is a TOC Item       if (item is TocItem)       {        //If the name of the layer is present then it was checked on        if(layerNodes.indexOf(TocItem(item).label) > -1)        {         //Check the Layer Checkbox in the TOC         TocItem(item).visible = true;         }        //Verify the status of this layer's Children        FetchNextLayer(TocItem(item), layerNodes);       }      }     }     //if there is nothing in the shared object tell the user      else      {      Alert.show("You have no saved preferences");      }          //check for unchecked items in the TOC     for each (item in toc.dataProvider)     {      if (item is TocItem)      {       //if the layer's name is not present in the array it was not checked       if(layerNodes.indexOf(TocItem(item).label) == -1)       {        //Uncheck the Group Layer Checkbox         TocItem(item).visible = false;        }       //Go ahead to verify the status of the layer's Children       FetchNextLayerUncheck(TocItem(item), layerNodes);      }     }              }            //If the Layer is visible, store its name in the input array    //and go ahead to verify rest of the nodes      private function FetchNextVisibleLayer(tocItem:TocItem, layerNodes:Array):void      {        //Check each and every node of the input Group Layer     for each (var item:TocItem in tocItem.children)     {         //If it is a group layer      if(item.isGroupLayer())       {       //and it is visible       if (item.visible == true)        {         //store it in the array        layerNodes[layerNodes.length] = item.label;        }       //Since current group layer can have group layers in it,        //keep checking until all the nodes are checked        FetchNextVisibleLayer(item, layerNodes);      }          else          {        //We are checking all nodes but don't want to store the lengend symbology nodes       //so we check if the item is visible and if its parent is a group layer           //A valid layer's parent in this case is a group layer where as a Legend Node's parent is an ordinary layer       if (item.visible == true && item.parent.isGroupLayer())            {              layerNodes[layerNodes.length] = item.label;           }         }         }      }            private function FetchNextLayer(tocItem:TocItem, layerNodes:Array):void    {     //go through the children     for each (var item:TocItem in tocItem.children)     {      //if the name of that layer appears in the layerNodes array      if(layerNodes.indexOf(item.label) > -1)      {       //then set the item's visible property to be true       item.visible = true;      }      //Since a group layer can have group layers, keep checking until all the nodes are checked      FetchNextLayer(item, layerNodes);     }    }            //Uncheck the Layer's checkbox, if the input array doesn't contain the Layer's name     private function FetchNextLayerUncheck(tocItem:TocItem, layerNodes:Array):void    {     for each (var item:TocItem in tocItem.children)     {      //if the name of that layer doesn't appear in the layerNodes array      if(layerNodes.indexOf(item.label) == -1)      {       //set the item's visbile property to be false       item.visible = false;      }      //Since a group layer can have group layers inside, keep checking until all the nodes are checked      FetchNextLayerUncheck(item, layerNodes);     }    }


Hopefully that will help people out a bit. Any suggestions for improvement are welcome.
Thanks
0 Kudos