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
form.tsx: pass the live watched record (ruleRecord) as dependentValues to data-source field widgets, so the gate and the popover re-scope reactively.
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.
Found while dogfooding
examples/app-showcasein the framework repo (showcase_invoice:contactisField.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.SchemaRendererContexthas noformValuesmember at all (packages/react/src/context/SchemaRendererContext.tsx— zero hits), soctx.formValuesis alwaysundefined— dead code.dependentValuesprop:packages/components/src/renderers/form/form.tsx:719-730passesdataSource: contextDataSourceto the field widget but nodependentValues;stripRegisteredFieldProps(form.tsx:135-153) merely forwards the prop forlookup/master_detail/treeif someone upstream set it — nobody does.ctx.data(static record scope). In create mode that's{}, sodependenciesMissing(LookupField.tsx:295-301) is permanentlytrue→ 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:
popoverFilter, LookupField.tsx:375-394).RecordPickerDialoggets only the staticlookupFilters(LookupField.tsx:1098-1116) — thedependsOnchain is never merged in.disabled={dependenciesMissing}, unlike the main trigger (:807).Fix direction
form.tsx: pass the live watched record (ruleRecord) asdependentValuesto data-source field widgets, so the gate and the popover re-scope reactively.LookupField.tsx: merge thedependsOnchain (param → value aseqfilters) into whatRecordPickerDialogreceives, and gate the browse-all button ondependenciesMissinglike the main trigger.