Using ArcGIS Desktop 10.2.2, Advanced license. I created a new coded domain for a string field. I added the domain to an existing field. When I edit the features, i would expect to get a list of the coded values from the domain as a dropdown menu. This is not happening. What am I missing - is there a simple check mark or radio button setting?
-
Your expectation is what I observe whenever I do this. I recommend that you edit your question to list all your steps in detail with pictures. By doing this I suspect that you will spot something astray in your procedure but if not then we will know exactly what you did, and be in a much better position to provide an answer.– PolyGeo ♦Commented Aug 7, 2014 at 21:55
-
If, as I suspect, the original poster had this question while working through Exercise 13b in "Esri ArcGIS Desktop Associate Certification Study Guide," as I did, then maffa's answer regarding subtypes is spot on. See the web page on Geonet titled "Errata sheet for Desktop Associate Study Guide book." There is a link to download the errata sheet on there.– LetaCommented Jul 20, 2016 at 23:14
3 Answers
Make sure subtypes have not been defined for one of the fields in the feature class you are assigning a domain to. In the Feature Class Properties, choose "Subtypes". If a subtype field has been defined, click into each row in the table "Subtypes" and add the domain in the table "Default Values and Domains" below. A dropdown menu will appear only for the features belonging to one of the subtypes for which you have added the domain.
If your feature class contains subtypes, it is not enough to see the domain assigned to the correct field in the "Fields" tab of the Feature Class Properties.
maffa's answer can be carried out programmatically using the optional 'subtype_code' parameter of arcpy.AssignDomainToField_management() where (all) the subtype codes and descriptions can be given as a list of strings e.g. ["0: Unknown", "1: Concrete", "2: Asphalt"]
The below function consistently adds coded text domains, forcefully if necessary. This function will remove any existing domains of the same name from the geodatabase (including from any existing subtypes if necessary), add it back and apply it to the provided list of features (including within any subtypes that exist). There are also options to set defaults and populate any empty fields with the default value. One caveat, the domain name and field name must match, but that could be changed fairly easily if needed.
Thanks to maffa and nlibassi for the solution and inspiration. Also, adding the domain twice was inspired by jinskipesri-southafrica-esridist in this thread https://community.esri.com/thread/120676. Not sure why it works, but it does. Finally, credit to rvburton (see https://community.esri.com/thread/198384-how-to-remove-domain-from-field-for-gdb) for the portion of this script that removes domains from subtypes.
def AddCodedTextDomain(feature_list, workspace, domain_name, code_list,
assign_default=False, populate_default=False):
"""
Applies the code_list as a domain to the list of feature classes.
Domain must be the same as the field name to which it is being applied.
:param feature_list: list of feature classes
:param workspace: the project's unique gdb
:param domain_name: name of the domain as a string, must be same as name
of field to which it is applied
:param code_list: list of codes as strings
:param assign_default: True to assign the first code in the code_list as
default
:param populate_default: True to populate existing features with the
default code
:return: None
"""
# Create unique list from provided
uniqueCodes = []
for code in code_list:
if code not in uniqueCodes:
uniqueCodes.append(code)
# Check for existence of domain; update domain if present, add domain if not
desc = arcpy.Describe(workspace)
domains = desc.domains
if domain_name in domains:
arcpy.AddMessage(domain_name + " is already specified as a domain")
try:
# try removing from all fields in all feature classes
existingFeatures = arcpy.ListFeatureClasses()
for existingFeature in existingFeatures:
fields = arcpy.ListFields(existingFeature)
for field in fields:
if field.domain == domain_name:
arcpy.RemoveDomainFromField_management(existingFeature,
field.name)
arcpy.AddMessage(domain_name + " domain removed from "
+ existingFeature + " " + field.name
+ " field")
# try removing from all fields in all subtypes
# Credit to:(https://community.esri.com/thread/
# 198384-how-to-remove-domain-from-field-for-gdb)
subtypes = arcpy.da.ListSubtypes(existingFeature)
for stcode, stdict in list(subtypes.items()):
for stkey in list(stdict.keys()):
# if there is a Subtype Field
if not stdict['SubtypeField'] == '':
st_code = "'{}: {}'".format(stcode, stdict['Name'])
# if no Subtype Field, use "#" in RemoveDomainFromField
# for subtype_code
else:
st_code = "#"
if stkey == 'FieldValues':
fields = stdict[stkey]
for field, fieldvals in list(fields.items()):
# if field has a domain
if not fieldvals[1] is None:
# and the domain is in our list
if fieldvals[1].name == domain_name:
# remove the domain
arcpy.AddMessage(fieldvals[1].name
+ " domain removed "
+ "from " + existingFeature
+ " field: " + field
+ " subtype: " + st_code)
arcpy.RemoveDomainFromField_management(
existingFeature, field, st_code)
arcpy.DeleteDomain_management(workspace, domain_name)
arcpy.CreateDomain_management(workspace, domain_name,
"Valid " + domain_name + "s",
"TEXT", "CODED")
for code in uniqueCodes:
arcpy.AddCodedValueToDomain_management(workspace, domain_name,
code, code)
for feature in feature_list:
try:
arcpy.AssignDomainToField_management(feature, domain_name,
domain_name)
# Check to make sure subtypes exist
subtypes = arcpy.da.ListSubtypes(feature)
if len(subtypes) == 1 and subtypes[0]['SubtypeField'] == '':
pass
else:
st_codes = [str(stcode) for stcode, stdict in list(subtypes.items())]
arcpy.AssignDomainToField_management(feature, domain_name,
domain_name, st_codes)
except arcpy.ExecuteError:
arcpy.AddMessage("--------------------------------"
"\n" + domain_name
+ " domain for feature \n\n"
+ str(feature) + "\n\n"
+ "could not be updated. Use "
"caution when populating attribute\n"
"---------------------------------")
arcpy.AddMessage(domain_name + " domain updated")
except arcpy.ExecuteError:
arcpy.AddMessage(domain_name + " domain could not be updated. Use "
"caution when populating attribute")
else:
arcpy.CreateDomain_management(workspace, domain_name,
"Valid " + domain_name + "s",
"TEXT", "CODED")
for code in uniqueCodes:
arcpy.AddCodedValueToDomain_management(workspace, domain_name,
code, code)
for feature in feature_list:
try:
arcpy.AssignDomainToField_management(feature, domain_name,
domain_name)
# Check to make sure subtypes exist
subtypes = arcpy.da.ListSubtypes(feature)
if len(subtypes) == 1 and subtypes[0]['SubtypeField'] == '':
pass
else:
st_codes = [str(stcode) for stcode, stdict in list(subtypes.items())]
arcpy.AssignDomainToField_management(feature, domain_name,
domain_name, st_codes)
arcpy.AddMessage(domain_name + " domain updated")
except arcpy.ExecuteError:
arcpy.AddMessage(domain_name + " domain could not be updated. Use "
"caution when populating attribute")
# Assign the first value as the default
if assign_default:
for feature in feature_list:
subtypes = arcpy.da.ListSubtypes(feature)
st_codes = [str(stcode) for stcode, stdict in list(subtypes.items())]
arcpy.AssignDefaultToField_management(feature, domain_name,
uniqueCodes[0], st_codes)
# Populate field with default values if Null
if populate_default:
arcpy.AddMessage("Populating default values")
for feature in feature_list:
where_clause = "{0} = '' OR {0} IS NULL".format(
arcpy.AddFieldDelimiters(feature, domain_name)
)
with arcpy.da.UpdateCursor(feature, domain_name, where_clause) as cursor:
for row in cursor:
row[0] = uniqueCodes[0]
cursor.updateRow(row)
Last caveat, I accept no liability if this blows up your geodatabase, just trying to help!