SfSkills Domains Docs GitHub

Home / admin / field-dependency-and-controlling

field-dependency-and-controlling

Dependent picklists in Salesforce: controlling field (picklist or checkbox), dependent picklist, valueSettings matrix in metadata, API behavior via SOAP/REST, LWC lightning-combobox with dependency.

Open the skill folder on GitHub


Field Dependency and Controlling

Activate when configuring dependent picklists — Salesforce's built-in mechanism for filtering a picklist's options based on another field's value. UI honors the matrix; the API does not enforce it the way users expect.

Before Starting

Questions to Ask Before Configuring

Ask these before opening Field Dependencies. Every one of them maps to a way this feature fails silently, and an assistant that skips them ships a matrix that looks correct in a demo org and leaks bad data in production.

AskWhy it mattersWhat a good answer adds
"Which paths write these two fields — the record page only, or also Data Loader, an integration, or Apex?"The filter is browser JavaScript that runs before the server sequence and nowhere else (Gotcha 6). Every other path saves anything.The list of paths a validation rule or before-save must survive — or a documented decision that UI-only is genuinely the whole surface
"Is the controlling field a picklist or a checkbox?"The matrix literals differ: value fullNames versus checked/unchecked (Gotcha 7). Getting it wrong ships an empty dropdown.The exact controllingFieldValue strings, settled before any XML exists
"Does this matrix already exist in the target org, and does anything need to be un-mapped?"Deploys add pairs and can never remove one (Gotcha 4). Un-mapping is a Setup task with its own change ticket.A split of the work into a deploy and a Setup edit, instead of a deploy that silently does half of it
"Which profiles and permission sets can see the controlling field?"A controlling field hidden by FLS drops out of controllerValues and the dependent picklist goes empty for exactly those users (Gotcha 1).The FLS row for both fields together, and the partner/community profiles that need an explicit fallback
"Does the object have record types, and which of them should offer each dependent value?"Availability is the intersection of record type and matrix, and Metadata API retrieval will not show you the gap (Gotcha 9).The RecordType.picklistValues entries per record type, checked in Setup rather than in the repo
"How deep is the chain — two fields, or does the dependent field control a third?"Each field sees only its immediate controller, and nothing clears a stale grandchild selection (Gotcha 2).The deploy order, the number of wire calls, and the clear-on-change logic a custom component owes
"What do we do about rows that already hold a combination the new matrix forbids?"Existing rows are untouched by a new matrix; they display blank in the UI while still returning a value in SOQL.A count from the verification SOQL in references/metadata-examples.md §9 and a decision to backfill, report, or ship the rule inactive first

What a proper configuration adds over just building the matrix in Setup: the same constraint is enforced on every write path rather than only in a browser, the record types actually expose the values the matrix enables, existing bad rows are counted before the rule starts rejecting them, and the pairs that were meant to be removed are actually removed instead of merely deleted from source control.


Core Concepts

Controlling vs Dependent

A controlling field determines which values of a dependent picklist are available. The mapping is a matrix stored in the dependent picklist's valueSettings.

<fields>
    <fullName>Category__c</fullName>
    <type>Picklist</type>
    <valueSet>
        <controllingField>Parent_Category__c</controllingField>
        <valueSetDefinition>
            <value><fullName>Laptops</fullName></value>
            <value><fullName>Desktops</fullName></value>
        </valueSetDefinition>
        <valueSettings>
            <controllingFieldValue>Computers</controllingFieldValue>
            <valueName>Laptops</valueName>
        </valueSettings>
        <valueSettings>
            <controllingFieldValue>Computers</controllingFieldValue>
            <valueName>Desktops</valueName>
        </valueSettings>
    </valueSet>
</fields>

UI vs API enforcement

Checkbox as controlling field

The matrix is a 2-column table, and its two column keys are the literals checked and unchecked — not true and false. The guide fixes them on controllingFieldValues: "The values in the list depend on the field type: • Checkbox: checked or unchecked. • Picklist: The fullname of the picklist value in the controlling field" (api_meta.txt:79250–79258). The checkbox field itself still stores and reads true/false everywhere else — in <defaultValue>, in SOQL, in Apex, in formulas. Only controllingFieldValue uses the other pair. See references/gotchas.md Gotcha 7.

Global Value Sets

Dependencies are per-field. GlobalValueSet "isn't a field itself" (api_meta.txt:79344–79347) and has no controllingField element — controllingField and valueSettings are elements of each consuming field's own ValueSet, so two fields sharing one GVS need two separately maintained matrices.

A GVS-backed field as the controlling side is unambiguous: the controller is referenced by name only. Whether a GVS-backed field may be the dependent side is UNVERIFIED (2026-09-05) — the Metadata API guide neither permits nor forbids it (controllingField, valueSetName and valueSettings are peer elements of ValueSet, api_meta.txt:45843–45858), while admin/picklist-and-value-sets Gotcha 6 records from field experience that Setup does not offer GVS-backed fields in the dependent-field list. Until that is settled, model the dependent side with a local valueSetDefinition. See references/metadata-examples.md §5.

Record Types add a second filter

RecordType.picklistValues is an independent second filter: each value it lists "is available in the record type that contains this component" (api_meta.txt:45051–45052). Availability is the intersection — a value must be listed on the record's record type and enabled for the selected controlling value. UNVERIFIED (2026-09-05): the guides do not state an evaluation order between the two filters, and for the observable outcome it does not matter; treat "record type restricts first" as a mental model, not a documented rule. See references/metadata-examples.md §6 and admin/record-types-and-page-layouts.

Common Patterns

Pattern: API validation rule for dependent picklist

AND(
  ISPICKVAL(Parent_Category__c, "Computers"),
  NOT(ISPICKVAL(Category__c, "Laptops")),
  NOT(ISPICKVAL(Category__c, "Desktops"))
)

Covers the case where API writes skip UI filtering.

Pattern: LWC dependent combobox

import { getPicklistValues } from 'lightning/uiObjectInfoApi';

@wire(getPicklistValues, {
    recordTypeId: '$recordTypeId',
    fieldApiName: PRODUCT_OBJECT.fieldApiName
})
picklistValues({ data }) {
    if (data) {
        this.controllerMap = data.controllerValues;
        this.valuesByController = data.values.reduce((acc, v) => {
            v.validFor.forEach(idx => {
                const key = Object.keys(this.controllerMap)[idx];
                (acc[key] = acc[key] ?? []).push({ label: v.label, value: v.value });
            });
            return acc;
        }, {});
    }
}

Pattern: Deploying the matrix

valueSettings blocks must include every (controllingValue, dependentValue) pair that should be enabled. Omitted pairs are disabled.

Decision Guidance

SituationApproach
Standard LEX formDependency matrix alone — UI enforces
Data Loader / API integrationsDependency + Validation Rule
LWC custom componentgetPicklistValues + build filter map client-side
Cascading 3+ levelsMultiple dependencies (each dep can be controlling for the next)
Different options per RecordTypeRecord Type picklist values + dependency matrix
Controlling by a non-picklist fieldUse Flow/formula to set a picklist controller, or convert logic
  1. Answer the seven questions above, then run python3 scripts/search_knowledge.py "dependent picklist controlling field" and read references/gotchas.md end to end. Gotchas 4, 6, 7 and 9 each change what you write, not just how you review it.
  2. Write the matrix as a table before writing XML — dependent values down the side, controlling values across the top, one tick per enabled pair. Copy the shape from templates/field-dependency-and-controlling-template.md; it is the artifact the validation rule and the record types are both derived from.
  3. Author the field files from references/metadata-examples.md — §2 for a picklist controller, §3 for a checkbox controller (checked/unchecked), §4 for a chain, §6 for the RecordType.picklistValues entries. Retrieve the fields first; never assemble a picklist field file from scratch (Gotcha 8).
  4. Restate the matrix as a validation rule (§7) for every non-UI write path the answers in step 1 identified. Skip this only where the answer was genuinely "record page only", and write that down.
  5. Run the checker — python3 skills/admin/field-dependency-and-controlling/scripts/check_field_dependency_and_controlling.py --manifest-dir force-app/main/default. It resolves every controllingField to a real picklist or checkbox on the object, rejects controllingFieldValues that are not in the controller's value set (including true/false on a checkbox controller), reports dependent values no controlling value enables, and flags dependent values missing from a record type that lists the field.
  6. Deploy in the order in §8 — controlling fields, dependent fields innermost-last, record types, validation rules — and use sf project deploy validate against production first.
  7. Verify in the org, not in the diff (§9): assert isDependentPicklist() and getController() from Apex (see references/examples.md Example 3), run the invalid-combination SOQL to size the existing backlog, and read the pair count off the Setup Field Dependencies grid. A green deploy is not evidence a pair was removed.

Review Checklist

Salesforce-Specific Gotchas

  1. API writes bypass dependency enforcement. Without a Validation Rule, a bad combination inserts cleanly, and later breaks UI views ("invalid picklist value").
  2. Adding a new value to the controlling picklist does NOT automatically enable it — you must edit valueSettings to enable the dependent values.
  3. Record Types filter first. A value disabled at the Record Type level is unreachable regardless of dependency matrix.
  4. Multi-select picklist cannot be a controlling field. Use a workaround with a normal picklist that captures the primary selection.
  5. Reporting filters don't respect dependencies — a stale invalid combination shows up unless you filter explicitly.
  6. getPicklistValues wire adapter is recordType-aware — passing the master record type returns all values regardless of record-type restrictions, which is why a component tested on Master and shipped to a record-typed page shows different options. UNVERIFIED (2026-09-05): the literal master record type id 012000000000000AAA is not stated in the Metadata API guide, the Object Reference, or the Apex guides; read it from getRecordTypeInfosByName().get('Master') rather than hard-coding it.

Output Artifacts

ArtifactDescription
valueSettings metadata blockXML matrix for deployable dependency
API-side Validation RuleEnforces matrix on API/DML writes
LWC dependent comboboxgetPicklistValues + client-side filter map
RecordType picklistValues blockRecord-type availability for every dependent value
Matrix worksheetThe signed-off table the XML, the rule, and the record types all derive from

Reference Files

FileRead it when
references/metadata-examples.mdWriting or reviewing the deployable XML — the matrix, a checkbox controller, a chain, record types, package.xml, deploy order, verification
references/gotchas.mdTen platform behaviours that break dependent picklists, including the add-only deploy and the browser-only filter
references/examples.mdBuilding the LWC side, or writing the Apex test that proves the dependency is still wired
references/well-architected.mdWeighing the matrix against a validation rule, chain depth, or a shared global value set — and for the source list
references/llm-anti-patterns.mdReviewing AI-generated dependency configuration or LWC combobox code
templates/field-dependency-and-controlling-template.mdCapturing the matrix, the answers to the questions above, and the deploy/verify record
scripts/check_field_dependency_and_controlling.pyValidating a manifest directory before deploy

Package files