Skip to content

Cascading lookup (dependsOn) broken in forms: stays gated after parent is chosen; table picker bypasses the dependent filter #2215

Description

@baozhoutao

Found while dogfooding examples/app-showcase in the framework repo (showcase_invoice: contact is Field.lookup('showcase_contact', { dependsOn: ['account'] })). Two independent breaks, both confirmed by source scan + browser repro against a source build.

Symptom 1 — dependent lookup stays gated forever after the parent is selected

Repro: New Invoice modal → pick an Account (chip "Northwind" shows) → the Contact lookup still renders the gated trigger "请先选择account" (data-testid="lookup-trigger-gated", disabled).

Root cause — the dependent values the gate reads are never the live form values:

  • packages/fields/src/widgets/LookupField.tsx:287-290 — resolvedDependentValues = dependentValuesProp ?? ctx.formValues ?? ctx.data.
  • SchemaRendererContext has no formValues member at all (packages/react/src/context/SchemaRendererContext.tsx — zero hits), so ctx.formValues is always undefined — dead code.
  • The form renderer never injects the dependentValues prop: packages/components/src/renderers/form/form.tsx:719-730 passes dataSource: contextDataSource to the field widget but no dependentValues; stripRegisteredFieldProps (form.tsx:135-153) merely forwards the prop for lookup/master_detail/tree if someone upstream set it — nobody does.
  • Net: the gate falls back to ctx.data (static record scope). In create mode that's {}, so dependenciesMissing (LookupField.tsx:295-301) is permanently true → the field can never be filled. In edit mode it's the saved record, so changing the parent in-form doesn't re-scope the child.

The form renderer already maintains a live watched snapshot for CEL rules (ruleRecord, form.tsx:275-288) — it just never hands it to lookup widgets.

Symptom 2 — the Level-2 table picker (browse-all) bypasses the cascade entirely

Repro: same modal, Account = Northwind already chosen → click the browse-all button next to Contact → dialog lists 121 records, page 1/13: Contoso/Fabrikam contacts, pagination-test contacts — everything. (It also opens fine while the field is still gated.)

Root cause:

  • The dependent filter chain is only applied to the quick-select popover query (popoverFilter, LookupField.tsx:375-394).
  • RecordPickerDialog gets only the static lookupFilters (LookupField.tsx:1098-1116) — the dependsOn chain is never merged in.
  • The browse-all button (LookupField.tsx:1080-1091) has no disabled={dependenciesMissing}, unlike the main trigger (:807).

Fix direction

  1. form.tsx: pass the live watched record (ruleRecord) as dependentValues to data-source field widgets, so the gate and the popover re-scope reactively.
  2. LookupField.tsx: merge the dependsOn chain (param → value as eq filters) into what RecordPickerDialog receives, and gate the browse-all button on dependenciesMissing like the main trigger.

Activity

  1. added 3 commits that reference this issue on Jul 4, 2026
    bce581a
    705f7bb
    226fde9
  2. added a commit that references this issue on Sep 1, 2026
    f73cab0
  3. added a commit that references this issue on Sep 9, 2026
    84ffdbc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions