Repository navigation
fix(fields): unlock dependent lookups on parent selection and enforce the cascade on every picker - #2216
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
… the cascade on every picker Fixes #2215. Dependent (cascading) lookups were broken end to end: - The depends_on gate never unlocked in create mode. LookupField resolved dependent values from ctx.formValues — a member SchemaRendererContext never had — and nothing injected the dependentValues prop, so with a fresh record (ctx.data = {}) the child lookup stayed disabled no matter what the user picked in the parent field. The form renderer now injects its live form values (the same reactive snapshot that drives field rules) as dependentValues for data-source fields. - The Level-2 table picker bypassed the cascade. The depends_on chain only reached the quick-select popover filter; RecordPickerDialog (and the search-first PeoplePicker) received just lookup_filters and listed the full unfiltered record set. Both pickers now take a baseFilter — a hard $filter constraint merged after lookupFilters and user filter-bar input so it can never be widened back out — and LookupField passes the dependent chain there, shares the same filter with the popover query, and disables the browse-all button while dependencies are missing. Verified in the browser against the app-showcase invoice form (contact depends_on account): the contact field unlocks after picking an account, the popover and the table picker both list only that account's contacts (2 rows instead of the full 121), and browse-all is disabled while gated. Co-Authored-By: Claude <noreply@anthropic.com>
os-zhuang
added a commit
that referenced
this pull request
Jul 16, 2026
) (#2620) Registered option widgets (field:select / field:radio / field:multiselect) that carry per-option `visibleWhen` + `dependsOn` cascading were excluded from the form renderer's `dependentValues` injection — only DATA_SOURCE_FIELD_TYPES (lookup/master_detail/…) received it. `stripRegisteredFieldProps` therefore dropped `dependentValues` before it reached SelectField, and with no `formValues` context fallback the widget's `dependsOn` gate never saw the controlling field: a cascading select stayed permanently gated on the "Select the parent first" hint even after the parent was chosen (reproduced on the showcase `showcase_cascade` B3 fixture — country → province never unlocked). Option field types now receive `dependentValues` too, mirroring the lookup fix (#2215/#2216). Verified end-to-end in the browser against the showcase B3 fixture: province gates until country is set, offers CN provinces for China, and re-filters to US states when country flips. Regression guard added in form-dependent-values.test.tsx driving the registered field:select path (the prior cascading-select test only covered the builtin `case 'select'` fallback, which reads options from the renderer's own ruleRecord and so never exercised the widget-injection gap). Co-authored-by: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This was referenced Sep 1, 2026
os-warren
pushed a commit
that referenced
this pull request
Sep 1, 2026
…lues
A `dependsOn` lookup column in an editable ObjectGrid was permanently
uneditable. `LookupField` resolves
`dependentValues ?? ctx.formValues ?? ctx.data ?? {}` and the grid's
`renderCellEditor` supplied none of the three, so the resolved record was
`{}` for every row, `dependenciesMissing` stayed `true`, and the trigger
rendered disabled ("Select region first") even when the row carried the
parent value.
PR #2216 closed #2215 in two halves: the form renderer injects its live
watched record, and every picker takes the `dependsOn` chain as a hard
`baseFilter`. Half 2 is host-independent and was already live here; half 1
is per-host and the grid never got it. This supplies that missing input and
re-implements no cascade.
INTERIM: `ctx.row` is the saved record, so a parent edited but not yet
saved in the same row does not re-scope the child. Carrying the staged
record needs a seventh member on `renderCellEditor`'s published context
type (declared in `@object-ui/types`, #6882, and pinned by exact type
equality), which is a contract change tracked separately.
The `dependsOn` case in `lookupPickerKeys-7154.test.tsx` pinned the gated
behaviour and is UPDATED, not deleted.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012wwHa4aaFybxXrfmfHioDM
akarma-synetal
pushed a commit
to akarma-synetal/objectui
that referenced
this pull request
Sep 9, 2026
…lues, so a `dependsOn` lookup column is no longer permanently uneditable (objectstack-ai#7193) * fix(plugin-grid): feed the inline cell editor the row as dependent values A `dependsOn` lookup column in an editable ObjectGrid was permanently uneditable. `LookupField` resolves `dependentValues ?? ctx.formValues ?? ctx.data ?? {}` and the grid's `renderCellEditor` supplied none of the three, so the resolved record was `{}` for every row, `dependenciesMissing` stayed `true`, and the trigger rendered disabled ("Select region first") even when the row carried the parent value. PR objectstack-ai#2216 closed objectstack-ai#2215 in two halves: the form renderer injects its live watched record, and every picker takes the `dependsOn` chain as a hard `baseFilter`. Half 2 is host-independent and was already live here; half 1 is per-host and the grid never got it. This supplies that missing input and re-implements no cascade. INTERIM: `ctx.row` is the saved record, so a parent edited but not yet saved in the same row does not re-scope the child. Carrying the staged record needs a seventh member on `renderCellEditor`'s published context type (declared in `@object-ui/types`, objectstack-ai#6882, and pinned by exact type equality), which is a contract change tracked separately. The `dependsOn` case in `lookupPickerKeys-7154.test.tsx` pinned the gated behaviour and is UPDATED, not deleted. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012wwHa4aaFybxXrfmfHioDM * chore(changeset): grid inline editor dependent values Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012wwHa4aaFybxXrfmfHioDM --------- Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #2215.
The two breaks
1. The
depends_ongate never unlocked in create mode.LookupFieldresolved dependent values asdependentValues ?? ctx.formValues ?? ctx.data, butSchemaRendererContexthas noformValuesmember (dead fallback) and nothing ever injected thedependentValuesprop. With a fresh record (ctx.data = {}) the child lookup stayed disabled forever, no matter what the user picked in the parent field.2. The Level-2 table picker bypassed the cascade.
The
depends_onchain only reached the quick-select popover's filter.RecordPickerDialog(and the search-firstPeoplePicker) received justlookup_filters, so "Browse all records" listed the full unfiltered set (121 contacts across 13 pages in the showcase repro).The fix
form.tsxinjects the live form values (the same reactiveruleRecordsnapshot that drives field rules) asdependentValues, forwarded to data-source field types only (stripRegisteredFieldPropsalready scoped that).RecordPickerDialog/PeoplePickergain abaseFilterprop — a hard$filterconstraint merged afterlookupFiltersand user filter-bar input, so filter-bar edits on the same field can never widen it back out.LookupFieldderives onedependentFilterfrom thedepends_onchain and shares it across all three candidate surfaces (popover query, table picker, PeoplePicker), and disables the browse-all button while dependencies are missing (same gate + hint as the trigger).Verification
$filterscoping (shorthand and{field, param}shapes),baseFilterwins overlookupFiltersand over filter-bar input on the same field,PeoplePickermerge order, and livedependentValuesinjection by the form renderer.contact depends_on account): contact unlocks after picking Northwind; popover and table picker both list only Northwind's 2 contacts (previously 121/13 pages); browse-all disabled while gated with the "select account first" hint.pnpm --filter @object-ui/fields --filter @object-ui/components buildclean; full test suite run — only pre-existing failure is the knownDATEFORMATtimezone flake in core (fails on main too, TZ-dependent).Co-Authored-By: Claude noreply@anthropic.com