Configure Popup Attributes Programmatically with ArcGIS API for Python

7598
17
Jump to solution
03-19-2018 04:58 PM
NathanielEvatt
New Contributor III

I am hoping to run a script that can hide certain fields from an ArcGIS Online web map.  In ArcGIS Online, I would accomplish this by opening a webmap, clicking the three dots of the layer I was interested in, selecting "configure pop-up" then selecting "Configure Attribute".  Finally from there I can edit the display options in the GUI shown below.  

Is this something that is currently configurable from the ArcGIS API for Python?

1 Solution

Accepted Solutions
AaronPulver
Esri Regular Contributor

This is possible but there's no "popup" API for it. You can get the webmap json, then edit the popup properties in the json, then update the webmap.

See the webmap spec here: popupInfo | ArcGIS for Developers  .

Code would be something like this (this hides every field in the popup):

import arcgis
import json

gis = arcgis.gis.GIS("https://arcgis.com", "username", "password")

item = gis.content.get("<item-id>")
item_data = item.get_data()
field_infos = item_data['operationalLayers'][0]['popupInfo']['fieldInfos']
for field in field_infos:
    field["visible"] = False

item_properties = {"text": json.dumps(item_data)}
item.update(item_properties=item_properties)

View solution in original post

17 Replies
NeilAyres
MVP Frequent Contributor

I don't see anything in here to toggle visibility.

arcgis.mapping module — arcgis 1.4.0 documentation 

0 Kudos
AaronPulver
Esri Regular Contributor

This is possible but there's no "popup" API for it. You can get the webmap json, then edit the popup properties in the json, then update the webmap.

See the webmap spec here: popupInfo | ArcGIS for Developers  .

Code would be something like this (this hides every field in the popup):

import arcgis
import json

gis = arcgis.gis.GIS("https://arcgis.com", "username", "password")

item = gis.content.get("<item-id>")
item_data = item.get_data()
field_infos = item_data['operationalLayers'][0]['popupInfo']['fieldInfos']
for field in field_infos:
    field["visible"] = False

item_properties = {"text": json.dumps(item_data)}
item.update(item_properties=item_properties)
by Anonymous User
Not applicable

Maybe I should start a different conversation, but our problem is that popups go away when overwriting a service from ArcGIS Pro, and we would like to automate the process of turning them back on (grr....).

This shows how to control which fields are displayed when the popups are turned on. Is it possible to enable popups programmatically?

Thank you,

Randy McGregor

LukasWürsch
New Contributor III

Thanks a lot for your code, this is very helpful. I could make this work for normal Hosted Feature Layers. My problem is that I couldn't make it work for a Hosted Feature Layer View, because 

item_data = item.get_data()

returns None, so I am not able to access 'fieldInfos'

Is this a general issue with Hosted Feature Layer Views or is there another way how I can configure the popup of these layers?

If necessary, I can provide an example layer to reproduce the issue. I would highly appreciate an answer.

Regards,

Lukas Würsch

0 Kudos
SeanSweeney
New Contributor III

Thanks Aaron.  I'm using this on Feature Layers, and it works great as long as the Visualization for the layer has been edited already through the UI.  For brand new just-published Feature Layers item.get_data() returns None.  Is there a way through the Python API to "touch" the Visualization and create the backing JSON before running item.get_data()?  I have over 150 layers to deal with so I don't want to have to update them all manually first.

AlderMaps
New Contributor III

I need to do exactly the same thing @SeanSweeney. I just need to tweak the JSON for my popups, but until the JSON exists in the map...well, it doesn't exist. I just want to stuff the default popupInfo > fieldInfos JSON in my map JSON and then be able to access and edit it. Note: for me, get_data() returns JSON but popupInfo and fieldInfos are not included. (I can verify they aren't in the map with ArcGIS Assistant, but are created when the popups are modified in the UI.)

AlderMaps
New Contributor III

@SeanSweeney Took all day but I think I have a method working to accomplish what we are looking to do--add the "default" popupInfo JSON to the webmap without having to configure anything in the UI ahead of time. TL;DR: have to get the popupInfo from the associated FeatureLayerCollection/Service Item Object.

It's unwieldy and clunky but it's the best I could do in the time allotted...adding here for posterity.

# Create Item object from item ID
itm = gis.content.get(itm_id)

# STEP 1: Make the dictionary of popupInfo and stuff in dict.

id_dict = [] # List to hold item IDs from which popupInfo is harvested
pop_dict = {} # Dict to hold popupInfo

wm = WebMap(itm)

for lyr in wm.layers:
    
    # Get the feature layer URL as key for dictionary
    fl_url = FeatureLayer(lyr).url["url"]
    
    # Get the itemID of the feature layer
    fl_itmid = FeatureLayer(lyr).url["itemId"]
    
    # Skip item ID if already done
    if fl_itmid in id_dict:
        continue
    
    # Add item ID to list to keep track of what services we've already checked
    id_dict.append(fl_itmid)
    
    # Get the Item itself
    flc_itm = gis.content.get(fl_itmid)
    
    # Get the item data (this is where the JSON we need lives...i.e.
    # ...this is what ArcGIS Assistant shows you when you click "View item JSON")
    flc_data = flc_itm.get_data()
    
    # Grab the value (list of layer info) at the key "layers"
    lyrs_info = flc_data["layers"]
    
    # Iterate through info for all layer info in the service
    for l in lyrs_info:
        
        # For each layer: make the key URL
        head = fl_url.rsplit("/",1)[0]
        tail = str(l["id"])
        key_url = f"{head}/{tail}"
        
        # FINALLY, WE GET OUR HANDS ON THE GODDAMNED POPUPINFO!!
        pop_info = l["popupInfo"]
    
        # Assign popupInfo to dict with feature layer URL as key
        pop_dict[key_url] = pop_info

# STEP 2: Assign the popupInfo to the correct layers in the webmap
itm_data = itm.get_data()

# Loop through operational layers
for ops_lyr in itm_data["operationalLayers"]:
    
    # Grab url (full URL including layer ID)
    ol_url = ops_lyr["url"]
    
    # Check whether popupInfo already exists for layer:
    if not "popupInfo" in ops_lyr:
        
        # Compare ops layer URL to url keys in dict from above
        if ol_url in pop_dict:
            
            # If there's a match, toss in the popupInfo!
            ops_lyr.update({"popupInfo": pop_dict[ol_url]})
            
            print(ol_url)
            print("popupInfo successfully added!\n")

# Update item_properties
itm_props = {"text": itm_data}
itm.update(item_properties = itm_props)

 

Sean-Sweeney
New Contributor II

Wow, thanks!  I have go through this more carefully when I get more time, but nothing's as unwieldy or clunky as having to use the UI for this so I'm sure it will be an improvement.

0 Kudos
AtmaMani
Esri Contributor

You can accomplish this by editing the visibility property of each field. You can do something like this

web_map_obj = WebMap(wm_item)
layer_1 = web_map_obj.layers[0]

#turn off visibility of field 1 of layer 1
layer_1.popupInfo.fieldInfos[0].visible = False

# update the web map
web_map_obj.update()