Contingent values are a data design feature that allow you to make values in one field dependent upon values in another field. In other words, contingent values are how you define a set of attribute Attributes are fields and values for a single feature or non-spatial record. They are typically stored in a database or service such as a feature service. Learn more values that are specifically valid in the context of other feature A feature is a single record, also known as a row, that represents a real-world entity. It typically contains a geometry (point, multipoint, polyline, or polygon) and attributes but it can also contain just attributes. Learn more attribute values. For example, a power pole dataset might use contingent values to specify what values are appropriate for poles based on other attributes Attributes are fields and values for a single feature or non-spatial record. They are typically stored in a database or service such as a feature service. Learn more . The voltage level for a pole determines what material values are valid; each material might have a set of appropriate heights from which to choose. Contingent values let you define all valid combinations of values for two or more attribute fields within a dataset.

Values in the dropdown are contingent values based on the previous entry.

What contingent values look like

You can author contingent values using ArcGIS Pro ArcGIS Pro is a professional desktop GIS application that can explore, visualize, analyze, and manage 2D and 3D data. Learn more and save them in a mobile map A mobile map package (MMPK) is a standalone file that contains one or more map definitions, including the basemap layers, data layers, layer styles, and pop-up styles for use in offline applications built with ArcGIS Maps SDKs for Native Apps. Learn more or scene package A mobile scene package (MSPK) is a standalone file that contains one or more scene definitions, including the basemap layers, elevation layers, data layers, layer styles, and pop-up styles for use in offline applications built with ArcGIS Maps SDKs for Native Apps. Learn more , standalone geodatabase A geodatabase is a spatial data storage format that can contain multiple datasets of geographic features and non-spatial tabular data, as well as attachments, field domain definitions, and relationships between layers/tables. Learn more , web map A web map is a map stored as a JSON object that defines properties such as the basemap layer, data layers, layer styles, and pop-up styles. Its JSON structure is defined by the web map specification. Learn more , web scene A web scene is a scene stored as a JSON object that defines properties such as the basemap layer, data layers, layer styles, and pop-up styles. Its JSON structure is defined by the web scene specification. Learn more , or feature service A feature service is a data service that provides access to spatial and non-spatial data in feature layers, feature layer views, and tables. Learn more .

Contingent values are defined in one or more field groups. A field group is a named collection of attribute Attributes are fields and values for a single feature or non-spatial record. They are typically stored in a database or service such as a feature service. Learn more fields in your dataset that have contingent values. Each field in a field group must have an associated domain. Contingent values are based on the field’s domain and represent a subset of the values the domain defines. See Introduction to attribute domains in the ArcGIS Pro documentation for more information about domains.

For each field group, contingent values define all combinations of appropriate values for the participating fields. The value you provide for each field depends on the type of domain associated with it (coded value or range). You can also provide special values to indicate that any value in the domain is considered valid or that a null value is valid (for fields that accept null values). Note that the any value also includes null.

The following image shows a field group that defines a set of contingent values for power poles. The fields Voltage, Material, and Height use coded value domains for their values, while Diameter uses a range domain. Poles that have a value of Wood for the Material field can have any value for Height that’s in the associated domain (or null) without violating the contingent values.

Contingent values that define all valid combinations for voltage levels, material types, pole height, and diameter.

Access contingent values in your app

Classes and helper methods are provided for reading contingent value definitions for a dataset and for determining contingent value violations for a specific feature A feature is a single record, also known as a row, that represents a real-world entity. It typically contains a geometry (point, multipoint, polyline, or polygon) and attributes but it can also contain just attributes. Learn more , allowing your app to incorporate contingent values into editing workflows. You might use drop down lists, for example, to provide the appropriate list of values based on other attributes Attributes are fields and values for a single feature or non-spatial record. They are typically stored in a database or service such as a feature service. Learn more that have been specified. Your app can also validate against contingent values to find violations before saving edits for a feature.

Contingent values can be read from an ArcGISFeatureTable. Here are some of the classes used to represent contingent values:

  • FieldGroup—Defines all possible contingent values for a set of fields. The contingent values definition contains a collection of field groups.

  • Contingency—Defines a set of contingent values for a field group.

  • ContingentValue—A base class that defines a possible value for a field participating in a field group. A contingent value can be one of the following:

In addition to these classes, the API provides the following helper methods on ArcGISFeatureTable. In many cases, these helper methods are all you need to provide contingent value support when editing the table A table is a non-spatial dataset in a feature service. All records in a table share the same set of fields. Learn more .

  • ArcGISFeatureTable.getContingentValues()—Returns contingent values for a provided feature A feature is a single record, also known as a row, that represents a real-world entity. It typically contains a geometry (point, multipoint, polyline, or polygon) and attributes but it can also contain just attributes. Learn more and attribute Attributes are fields and values for a single feature or non-spatial record. They are typically stored in a database or service such as a feature service. Learn more field.

  • ArcGISFeatureTable.validateContingencyConstraints()—Validates a feature A feature is a single record, also known as a row, that represents a real-world entity. It typically contains a geometry (point, multipoint, polyline, or polygon) and attributes but it can also contain just attributes. Learn more against contingent values defined for the dataset.

Edit with contingent values

Contingent values do not enforce data integrity or attribute Attributes are fields and values for a single feature or non-spatial record. They are typically stored in a database or service such as a feature service. Learn more rules for the data. However, you can design your app to guide the user through an edit workflow where contingent values provide appropriate choices and validation checks before edits are saved. For example, you could enforce ordered steps in your editing workflow to ensure that the current set of values you display for the editor are based on the previous inputs.

Values in the dropdown are contingent values based on the previous entry.

Get contingent values

Contingent values are derived from values in an attribute Attributes are fields and values for a single feature or non-spatial record. They are typically stored in a database or service such as a feature service. Learn more domain for the dataset. Since domains can either be a list of coded values or a range of acceptable numeric values, the same is true for contingent values. Each set of contingent values is defined from a subset of the domain. If your domain for pole diameter defines a range of 6 to 18 inches, for example, any contingent values must be within this range, for example 7 to 10 inches. Likewise, coded value domains define a set of acceptable values and the contingent values must contain a subset of those items.

To get the contingent values for a field, use the ArcGISFeatureTable.getContingentValues()helper method and pass the current feature A feature is a single record, also known as a row, that represents a real-world entity. It typically contains a geometry (point, multipoint, polyline, or polygon) and attributes but it can also contain just attributes. Learn more and the field name. The helper method looks at the current values defined for other attributes Attributes are fields and values for a single feature or non-spatial record. They are typically stored in a database or service such as a feature service. Learn more of the feature to return a set of the appropriate contingent values for the specified field.

The following code gets all contingent coded values for the specified field based on the other attribute Attributes are fields and values for a single feature or non-spatial record. They are typically stored in a database or service such as a feature service. Learn more values for the provided feature A feature is a single record, also known as a row, that represents a real-world entity. It typically contains a geometry (point, multipoint, polyline, or polygon) and attributes but it can also contain just attributes. Learn more .

// Store a hashmap of values from the contingent values definition.
HashMap<String, Object> availableValues = new HashMap<>();
// Get all contingent values defined for a specified field name.
// The attribute values of the feature determine which contingent values are returned.
// Assume that inFeature has these attribute values:
// Voltage="Low"; Material="Composite"; Height="35"; and Diameter=7 .
// If the field name is "Material", the resulting contingent values are:
// Composite; Wood; Carbon fiber.
fieldName = "Material";
ContingentValuesResult contingentValuesResult =
polesFeatureTable.getContingentValues(inFeature, fieldName);
// Get a list of contingent values for a specified field group.
Map<String, List<ContingentValue>> contingentVals =
contingentValuesResult.getContingentValuesByFieldGroup();
String fieldGroupName = "pole_contingent_values";
List<ContingentValue> fieldGroupContingentVals = contingentVals.get(fieldGroupName);
//Get the contingent values for a specified field group.
if (fieldGroupContingentVals != null) {
// Loop through all contingent values.
for (ContingentValue cv : fieldGroupContingentVals) {
// Add coded values to the hashmap (name and code).
if (cv instanceof ContingentCodedValue contingentCodedValue) {
availableValues.put(
contingentCodedValue.getCodedValue().getName(), contingentCodedValue.getCodedValue().getCode()
);
}

If the contingent values are from a range domain, you can return the minimum and maximum values for the valid range.

// (continued from above)
// A contingent range value has a minimum and a maximum value.
else if (cv instanceof ContingentRangeValue contingentRangeValue) {
availableValues.put("min", contingentRangeValue.getMinValue());
availableValues.put("max", contingentRangeValue.getMaxValue());
}

If a ContingentAnyValue is defined for the field, you can provide all values from the field’s domain as valid edit choices.

// (continued from above)
else if (cv instanceof ContingentAnyValue) {
// Get the domain for this field.
Domain domain = polesFeatureTable.getField(fieldName).getDomain();
if (domain instanceof CodedValueDomain codedValueDomain) {
// Add all values from the field's domain.
List<CodedValue> codedValuesList = codedValueDomain.getCodedValues();
for (CodedValue codedValue : codedValuesList) {
availableValues.put(codedValue.getName(), codedValue.getCode());
}
}
}
} // end for (ContingentValue cv : fieldGroupContingentVals).
} // end if (fieldGroupContingentVals != null).

Validate edits against contingent values

To see if a feature’s attribute Attributes are fields and values for a single feature or non-spatial record. They are typically stored in a database or service such as a feature service. Learn more values conform to the defined contingent values, call the ArcGISFeatureTable.validateContingencyConstraints() helper method and pass a feature A feature is a single record, also known as a row, that represents a real-world entity. It typically contains a geometry (point, multipoint, polyline, or polygon) and attributes but it can also contain just attributes. Learn more . The method returns a collection of ContingencyConstraintViolation that you can use to enforce edit restrictions or provide warnings to the user.

Each contingency constraint violation will indicate if it is a warning or an error, and which field group contained the violated contingent value. A violation is considered an error if the field group is marked as restrictive. A restrictive field group means that edits to any of the participating fields should conform to previously defined contingent values. If a field group is not restrictive, then a violation alert is considered a warning.

// Get any contingency constraint violations for the new feature.
List<ContingencyConstraintViolation> contingencyValueViolations =
polesFeatureTable.validateContingencyConstraints(inFeature);
// If there are no violations, let the user save.
if (contingencyValueViolations.isEmpty()) {
saveFeatureButton.setDisable(false);
new Alert(Alert.AlertType.INFORMATION,"Contingent values validated").showAndWait();
return;
}
// Loop through contingency violations and show messages for errors and warnings.
// Include the name of the field group that had the violation.
String msg = "Contingency value violation for field group(s): ";
for (ContingencyConstraintViolation violation : contingencyValueViolations) {
msg = msg + "'" + violation.getFieldGroup().getName() + "' ";
}
new Alert(Alert.AlertType.WARNING,msg).showAndWait();