Select to view content in your preferred language

Create nested group layers in a Web Map

223
3
Jump to solution
3 weeks ago
Labels (1)
MaryHooper
New Contributor

I am trying to create nested group layers using Python. I am able to create group layers and add them to a webmap on Enterprise Portal 11.2. I wrote the code several different ways and haven't been able to get nested group layers to work. The code below works for group layer, but when I add the line that would add the nested layer it doesn't work. I get an this error: AttributeError: 'GroupLayer' object has no attribute 'properties'. 

This is the simplest version of the code. Any help is appreciated.

MaryHooper_1-1766509597651.png

 

 

 

 

0 Kudos
1 Solution

Accepted Solutions
Clubdebambos
MVP Regular Contributor

Hi @MaryHooper,

There is probably a couple of ways to do this. Through the Map object like you are attempting and my example follows suit, or you can manipulate the JSON from the WebMap definition in the WebMap item object instead.

Create the nesting before adding the groups. Take the below for example where I add layer3 and 4 as a SubGroup (nested list) when using add(). When using the title option it will name all groups (parent and children) the same, so you have to account for that and update the title of the subgroup(s) separately.

I have used Feature Layers from a Feature Service below, but you can also use map.content.layers[-1] or other index to grab a Feature Layer object from the map itself.

 

from arcgis.gis import GIS
from arcgis.map import Map

gis = GIS("home")

## Web Map item object
webmap_item = gis.content.get("WM_ITEM_ID")

## Map object
webmap = Map(webmap_item)

## FeatureLayer objects
layer1 = gis.content.get("FS_ITEM_ID").layers[0]
layer2 = gis.content.get("FS_ITEM_ID").layers[1]
layer3 = gis.content.get("FS_ITEM_ID").layers[2]
layer4 = gis.content.get("FS_ITEM_ID").layers[3]

## add to Map object
webmap.content.add(
    item = [[layer3, layer4], layer1, layer2], # added to map from bottom up
    options = {
        "title" : "Group Layer" #this will name the group and sub group the same
    }
)

## update the sub group name
webmap.content.layers[0].layers[0].title = "Sub Group"

## update the Map object
webmap.update()

 

I hope that helps, but let me know if anything is not clear.

All the best,

Glen

~ learn.finaldraftmapping.com

View solution in original post

3 Replies
Brian_McLeer
MVP Regular Contributor

I don't have a script that creates nested group layers, but I have one that updates pop-ups in webmaps. These snippets may be of use. I have webmaps that have group layers nested 2 or 3 levels down. 

def find_target_group_layer(layers: List[Dict[str, Any]], target_name: str) -> Optional[Dict[str, Any]]:
    """
    Find the target group layer by name, searching recursively if needed.

    Args:
        layers: List of layer dictionaries to search
        target_name: Name of the group layer to find

    Returns:
        The target group layer dictionary if found, None otherwise
    """
    logger.info(f"Searching for target group layer: '{target_name}'")

    for layer in layers:
        # Check the title first
        layer_title = layer.get("title", "")

        if layer_title == target_name:
            logger.info(f"[SUCCESS] Found target group layer: '{target_name}'")
            return layer

        # If this is a group layer, search its nested layers
        if "layers" in layer and layer["layers"]:
            result = find_target_group_layer(layer["layers"], target_name)
            if result:
                return result

    logger.warning(f"[WARNING] Target group layer '{target_name}' not found")
    return None
def process_layers_recursive(layers: List[Dict[str, Any]], layer_name_map: Dict[int, str],
                            layer_path: str = "") -> int:
    """
    Recursively process all layers, including nested layers within group layers.

    Args:
        layers: List of layer dictionaries to process
        layer_name_map: Mapping of layer IDs to names
        layer_path: String representing the current path (for logging)

    Returns:
        Count of layers successfully updated
    """
    updated_count = 0

    for layer in layers:
        layer_title = get_layer_name(layer, layer_name_map)
        full_path = f"{layer_path}/{layer_title}" if layer_path else layer_title

        # Check if this is a group layer with nested layers
        if "layers" in layer and layer["layers"]:
            logger.info(f"Found group layer: {full_path} with {len(layer['layers'])} nested layer(s)")
            # Recursively process nested layers
            nested_count = process_layers_recursive(layer["layers"], layer_name_map, full_path)
            updated_count += nested_count
        else:
            # This is a regular layer, update its popup
            if update_layer_popup(layer, layer_name_map, layer_path):
                updated_count += 1

    return updated_count

 

0 Kudos
Clubdebambos
MVP Regular Contributor

Hi @MaryHooper,

There is probably a couple of ways to do this. Through the Map object like you are attempting and my example follows suit, or you can manipulate the JSON from the WebMap definition in the WebMap item object instead.

Create the nesting before adding the groups. Take the below for example where I add layer3 and 4 as a SubGroup (nested list) when using add(). When using the title option it will name all groups (parent and children) the same, so you have to account for that and update the title of the subgroup(s) separately.

I have used Feature Layers from a Feature Service below, but you can also use map.content.layers[-1] or other index to grab a Feature Layer object from the map itself.

 

from arcgis.gis import GIS
from arcgis.map import Map

gis = GIS("home")

## Web Map item object
webmap_item = gis.content.get("WM_ITEM_ID")

## Map object
webmap = Map(webmap_item)

## FeatureLayer objects
layer1 = gis.content.get("FS_ITEM_ID").layers[0]
layer2 = gis.content.get("FS_ITEM_ID").layers[1]
layer3 = gis.content.get("FS_ITEM_ID").layers[2]
layer4 = gis.content.get("FS_ITEM_ID").layers[3]

## add to Map object
webmap.content.add(
    item = [[layer3, layer4], layer1, layer2], # added to map from bottom up
    options = {
        "title" : "Group Layer" #this will name the group and sub group the same
    }
)

## update the sub group name
webmap.content.layers[0].layers[0].title = "Sub Group"

## update the Map object
webmap.update()

 

I hope that helps, but let me know if anything is not clear.

All the best,

Glen

~ learn.finaldraftmapping.com
MaryHooper
New Contributor

Thank you, that worked. While I was waiting on this, I did manage to do it with the JSON. It's nice to know how to do it either way.

0 Kudos