Hi all,
I am seeking clarification and examples re: workflows to copy forms (and/or other layer properties, e.g. popup configs) from one layer to another.
I have found various resources indicating that it is possible to script workflows to copy various properties from one layer and apply them to another, typically by interacting with the item JSON, for example the notebook shared in this thread and the workflows and scripts described here.
In all the examples or threads I have found, the workflow is copying properties between layers that are in the same map, or from the same feature service. I would like to be able to configure a form, popup, etc., on a given layer, and be able to copy that configured property to entirely separate layers from different services assuming the source and target layer have the same fields.
Does anyone know if it is possible to copy things like forms and popup configurations between completely separate layers - not in the same map, not from the same feature service - as long as the fields are the same between the two layers? If so, how does this workflow need to differ from the examples using layers from the same map or service? Can I use the same approach and simply specify the URLs for the respective source and target layers' feature services or is there more to it? Am I missing something fundamental about the structure of hosted layers or feature services that would make this impossible?
Thanks in advance for any insights!
Solved! Go to Solution.
Hi @JasperRomero,
This is possible. All you need to do is get familiar with the WebMap JSON definition, and know the difference between a layer in a WebMap (which references a Feature Layer from a Feature Service) and a Feature Layer in a Feature Service.
To get familiar with the JSON for a WebMap, create one manually how it would generally function with your web forms, symbology, popups, etc. Then use the code below to print the definition for that WebMap to screen.
from arcgis.gis import GIS
import json
## access AGOL
agol = GIS("home")
## get the WebMap as an Item object
wm_item = agol.content.get("WM_ITEM_ID")
## print the WebMap definition to screen
wm_def = wm_item.get_data()
print(json.dumps(wm_def, indent=4))
The great thing about this WebMap definition is that you can manipulate it to update the components of your WebMap (extent, functionality like search and time sliders, layer properties like opacity, symbology, and popups) and you can also copy the granular components and apply to another WebMap definition.
You can access the definition just like any other Python dictionary. For example the "operationalLayers" represent all the layers in your WebMap. The operationalLayers is a list of dictionaries where each dictionary is a layer definition.
ol_list = wm_def["operationalLayers"]
print(json.dumps(ol_list, indent=4))
You need to be wary is your layers are in a Group layer, you would need to account for this if needed. For now we will continue without Group layers in mind. Take a look at the properties associated with each layer in your WebMap, there will be some common such as ["id", "title", "url", "itemId"...]. You can find more about these properties and others from the WebMap Specification here.
If you have forms set up on your layers they will have a "formInfo" property. Let's say the first layer in my operationalLayers list has forms, I can access as per the below snippet.
## index 0 in the operationalLayers is the first layer - the bottom-most layer in the WebMap
web_form = wm_def["operationalLayers"][0]["formInfo"]
print(json.dumps(web_form), indent=4)
Granted that your other WebMap has a layer with the same schema, or at least the fields from the original web form, you can copy the form definition and apply it to another layer in another WebMap. You can even manipulate the definition should you need to update some of the "formElements"/"expressionInfos" before apply to the other layer. Below, we will simply take the form as is and apply to another layer in another WebMap.
## get other WebMap as an Item object
other_wm_item = agol.content.get("OTHER_WM_ITEM_ID")
## get the other WebMap definition
other_wm_def = other_wm_item.get_data()
## access the layer of interest to apply the form to
## below as an example I have used the 3rd layer
other_wm_def[operationalLayers][2]["formInfo"] = web_form
## Update the other WebMap Item object definition
update_properties = {"text" : other_wm_def}
other_wm_item.update(item_properties=update_properties)
You could also take the entire WebMap layer definition (a dictionary), and add/append/insert into the operationalLayers definition of the target WebMap to add the layer with all the same properties such as symbology, popups, forms etc.
You can grab the symbology or popups from Feature Layers and apply to layers in a WebMap with a similar workflow, you would grab the JSON definition for the Feature Layer (Feature Service) for symbology or popups and apply like above. One thing to note is that you access the definition for Feature Layers differently from a WebMap, get_data() won't work on a Feature Service, but that's a different question.
###Gte the Feature Service as an Item object
fs_item = agol.content.get("FS_ITEM_ID")
## get the Feature Layer of interest
fl = fs_item.layers[0]
## print the Feature Layer Definition
print(fl.properties)
Overall, once you get comfortable with the JSON/definition of the WebMap (get_data) you can manipulate however you like. Make use of the WebMap Specification to for further clarification on properties in the WebMap definition.
Note: I have wrote the above from memory, so I may need to come back and alter some of the snippets, but it will get you started with what you want to achieve.
All the best,
Glen
Hi @JasperRomero,
This is possible. All you need to do is get familiar with the WebMap JSON definition, and know the difference between a layer in a WebMap (which references a Feature Layer from a Feature Service) and a Feature Layer in a Feature Service.
To get familiar with the JSON for a WebMap, create one manually how it would generally function with your web forms, symbology, popups, etc. Then use the code below to print the definition for that WebMap to screen.
from arcgis.gis import GIS
import json
## access AGOL
agol = GIS("home")
## get the WebMap as an Item object
wm_item = agol.content.get("WM_ITEM_ID")
## print the WebMap definition to screen
wm_def = wm_item.get_data()
print(json.dumps(wm_def, indent=4))
The great thing about this WebMap definition is that you can manipulate it to update the components of your WebMap (extent, functionality like search and time sliders, layer properties like opacity, symbology, and popups) and you can also copy the granular components and apply to another WebMap definition.
You can access the definition just like any other Python dictionary. For example the "operationalLayers" represent all the layers in your WebMap. The operationalLayers is a list of dictionaries where each dictionary is a layer definition.
ol_list = wm_def["operationalLayers"]
print(json.dumps(ol_list, indent=4))
You need to be wary is your layers are in a Group layer, you would need to account for this if needed. For now we will continue without Group layers in mind. Take a look at the properties associated with each layer in your WebMap, there will be some common such as ["id", "title", "url", "itemId"...]. You can find more about these properties and others from the WebMap Specification here.
If you have forms set up on your layers they will have a "formInfo" property. Let's say the first layer in my operationalLayers list has forms, I can access as per the below snippet.
## index 0 in the operationalLayers is the first layer - the bottom-most layer in the WebMap
web_form = wm_def["operationalLayers"][0]["formInfo"]
print(json.dumps(web_form), indent=4)
Granted that your other WebMap has a layer with the same schema, or at least the fields from the original web form, you can copy the form definition and apply it to another layer in another WebMap. You can even manipulate the definition should you need to update some of the "formElements"/"expressionInfos" before apply to the other layer. Below, we will simply take the form as is and apply to another layer in another WebMap.
## get other WebMap as an Item object
other_wm_item = agol.content.get("OTHER_WM_ITEM_ID")
## get the other WebMap definition
other_wm_def = other_wm_item.get_data()
## access the layer of interest to apply the form to
## below as an example I have used the 3rd layer
other_wm_def[operationalLayers][2]["formInfo"] = web_form
## Update the other WebMap Item object definition
update_properties = {"text" : other_wm_def}
other_wm_item.update(item_properties=update_properties)
You could also take the entire WebMap layer definition (a dictionary), and add/append/insert into the operationalLayers definition of the target WebMap to add the layer with all the same properties such as symbology, popups, forms etc.
You can grab the symbology or popups from Feature Layers and apply to layers in a WebMap with a similar workflow, you would grab the JSON definition for the Feature Layer (Feature Service) for symbology or popups and apply like above. One thing to note is that you access the definition for Feature Layers differently from a WebMap, get_data() won't work on a Feature Service, but that's a different question.
###Gte the Feature Service as an Item object
fs_item = agol.content.get("FS_ITEM_ID")
## get the Feature Layer of interest
fl = fs_item.layers[0]
## print the Feature Layer Definition
print(fl.properties)
Overall, once you get comfortable with the JSON/definition of the WebMap (get_data) you can manipulate however you like. Make use of the WebMap Specification to for further clarification on properties in the WebMap definition.
Note: I have wrote the above from memory, so I may need to come back and alter some of the snippets, but it will get you started with what you want to achieve.
All the best,
Glen
Hi Glen,
Thank you so much for the thorough response! This is exactly the kind of info I was looking for. Lots to work through here so I may follow up with another question or two at some point, but this gives me a very helpful template to guide my learning and understanding.
Best,
Jasper