Select to view content in your preferred language

Configure Layer Form based on Layer's Popup

185
1
a week ago
GISDataTasPorts
Occasional Contributor

My web map layers all have optimal popups configured, because this is done automatically using arcpy (with CIM), before the layers are automatically published from ArcGIS Pro to AGOL (using the same arcpy script that configures the popups).

In the ArcGIS Online Field Maps Designer, I can interactively create nice forms for these layers by using the 'Convert from Popup' button.

However, I produce these web maps on a regular basis and they have a lot of layers.  I would like to automate the 'Convert from Popup' action (and avoid the group element which this creates).

Is/are there any (set of) function(s) in ArcGIS API for Python to perform the 'Convert from Popup' or do I have to develop this myself? I'd like to avoid a lot of time re-inventing the wheel.

If I have to do this myself, are there any examples of how this can be done in Python?  If I have to do it manually, I guess I would have to cycle through the popup elements, and convert each of them to form elements, but this is not something I've done before so it may take me some time to figure it out.

0 Kudos
1 Reply
Clubdebambos
MVP Regular Contributor

Hi @GISDataTasPorts,

There is no option with the ArcGIS API for Python that mimics that Convert popup (to form). If the maps are being produced regularly with the same layers/tables you can create template JSON files.

  1. Create the forms manually one time
  2. Extract the formInfo for each to a JSON file
  3. Apply to layers/tables programmatically

 

Export JSON file

from arcgis.gis import GIS
import json

## access AGOL
agol = GIS("home")

## get the Web Map as an Item object
wm_item = agol.content.get("WM_ITEM_ID")

## get the Web Map JSON definition as a dictionary
wm_item_data = wm_item.get_data()

## set the output folder
form_output_fldr = r"C:\Path\to\template\folder"

## the layer names as they appear in the Web Map
layer_names = [
    "Layer 1",
    "Layer 2",
    "Layer 3",
    ...,
    "Layer N"
]

## the table names as they appear in the Web Map
table_names = [
    "Table 1",
    "Table 2",
    "Table 3",
    ...,
    "Table N"
]

## for each layer in the Web Map
for lyr in wm_item_data["operationalLayers"]:
    ## if the layer is in the list
    if lyr["title"] in layer_names:

        try:
            ## output file path
            form_output_file = f"{form_output_fldr}\\{lyr['title']}.json"

            ## get the formInfo definition
            form_def = lyr["formInfo"]

            ## export to JSON file with same name as the layer
            with open(form_output_file, 'w', encoding='utf-8') as f:
                json.dump(form_def, f, ensure_ascii=False, indent=4)
        except KeyError:
            print(f"No form for {lyr['title']}")

## for each table in the Web Map
for tbl in wm_item_data["tables"]:
    ## if the tableis in the list
    if tbl["title"] in table_names:

        try:
            ## output file path
            form_output_file = f"{form_output_fldr}\\{tbl['title']}.json"
 
            ## get the formInfo definition
            form_def = tbl["formInfo"]

            ## export to JSON file with same name as the layer
            with open(form_output_file, 'w', encoding='utf-8') as f:
                json.dump(form_def, f, ensure_ascii=False, indent=4)
        except KeyError:
            print(f"No form for {tbl['title']}")

 

Apply JSON to formInfo

from arcgis.gis import GIS
import json

agol = GIS("home")

folder = r"C:\Path\to\template\folder"

## the layer names as they appear in the Web Map
layer_names = [
    "Layer 1",
    "Layer 2",
    "Layer 3",
    ...,
    "Layer N"
]

## the table names as they appear in the Web Map
table_names = [
    "Table 1",
    "Table 2",
    "Table 3",
    ...,
    "Table N"
]

## the web maps to update
wm_ids = {
    "WebMap 1" : "WM_ITEM_ID",
    "WebMap 2" : "WM_ITEM_ID",
    "WebMap 3" : "WM_ITEM_ID"
}

## for each web map
for wm_name, wm_item_id in wm_ids.items():

    print(wm_name)

    ## get the web map as an Item object
    wm_item = agol.content.get(wm_item_id)

    ## get the web map definition as a dictionary
    wm_item_data = wm_item.get_data()

    ## iterate over the layers
    for lyr in wm_item_data["operationalLayers"]:
        try:
            ## if the layer name matches a layer in the list
            if lyr["title"] in layer_names:
                ## get the matching JSON file
                json_definition_file = f"{folder}\\{lyr['title']}.json"
                ## update the formInfo
                with open(json_definition_file) as json_def:
                    form_def = json.load(json_def)
                    lyr["formInfo"] = form_def
        except FileNotFoundError:
            print(f"No form file for {lyr['title']}")

    ## do the same for tables
    for tbl in wm_item_data["tables"]:
        try:
            if tbl["title"] in table_names:
                json_definition_file = f"{folder}\\{tbl['title']}.json"
                with open(json_definition_file) as json_def:
                    form_def = json.load(json_def)
                    tbl["formInfo"] = form_def
        except FileNotFoundError:
            print(f"No form file for {tbl['title']}")

    item_properties = {"text":wm_item_data}
    wm_item.update(item_properties=item_properties)

 

You could also write your own converter using the Form Input classes from the API.

All the best,

Glen

 

 

~ learn.finaldraftmapping.com
0 Kudos