You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Create dialog ignores a field's defaultValue — a required select with a default renders empty and forces a manual choice #4047
Migrated from objectstack-ai/objectstack#5150 under the file-at-destination ruling (objectstack-ai/objectstack#7167, maintainer 2026-08-10). Originally filed 2026-08-04T06:27:24Z. The full prior thread — including triage rulings and hold/restart conditions — remains on the source issue and MUST be read before acting on this card.
Summary
A field that declares defaultValue and required: true renders in the create dialog with no value selected and a required marker, so the user is forced to pick something the system already knows. The default is served to the console; the create form just does not apply it.
Measured 2026-08-04, @objectstack/console shipped with 17.0.0-rc.1, zh-CN console, fresh database, object create dialog from an object list page.
Expected: the create dialog opens with Draft preselected. Actual: the select shows its placeholder (请选择 / Select…) with a required asterisk. Nothing is preselected; the form cannot be submitted until the user opens the dropdown and picks a value by hand.
The server side is fine — a create that omits the field entirely is accepted and stored as draft:
So this is purely the create form not seeding its default values from the object schema.
Why it matters beyond ergonomics
For a status-like field the forced choice is not neutral — every option is one click away and some of them have side effects. In our app choosing Approved at creation time immediately publishes a grade onto the parent customer record from a scorecard with no facts entered yet. The safe value is the declared default; the UI just refuses to use it.
More generally: defaultValue + required is a normal, correct way to model "this has a sensible starting value". Right now that combination produces the worst create-form experience of any modelling choice — strictly worse than declaring no default at all.
Note
There is code in plugin-form-*.js that builds default values from the object schema —
— but the object create dialog does not appear to go through it. If that is a component-wiring gap rather than a missing feature, it may be a small fix.
Workaround we shipped
We removed the field from the create form entirely (via a visibleWhen predicate keyed on the record's autonumber being empty) and let the server apply the default. That works, but it is a workaround for the form not honouring metadata it already has — and it only works because conditional visibility happens to be usable here; see objectstack-ai/objectstack#5149 for the ways it is not.
Claim: PM loop round 2 (objectui whole-repo seat — queue fill per the maintainer's 2026-08-10 five-concurrent directive)
Session: session_017Qqyix2QcnpUC9XeYVDzx3
Branch: claude/issue-4047-create-dialog-defaults
Worktree: objectui-issue-4047
Domain: repo:objectui (whole-repo seat)
File surface: the object create dialog's form-seeding path — expected around packages/plugin-form/src/ObjectForm.tsx (default seeding exists at :825 on origin/main) and/or the app-shell create-dialog wiring that bypasses it; plus tests. ⛔ Region-exclusive vs the in-flight #3569 branch (baozhoutao): do not touch GridField/grid-column files in packages/fields / packages/plugin-form. If the true producer of the defect is in another package than expected, report and fix at the producer (state where and why in the PR body) — do not patch a consumer.
Container & model: M, mode:subagent, model: opus
Serial constraints cleared: no open claim or PR on the create-dialog path; #3569's pushed branches touch GridField.tsx + showcase fixtures (disjoint files, region declared above).
Premise re-verified at dispatch: seeding logic exists (ObjectForm.tsx:825 reads field.defaultValue); the card's server-side reading (create-omitting-field stores the default) makes this a console-only wiring defect, per the source triage (objectstack#5150).
What shipped: create forms across all six object-form containers now open with the schema's declared static defaultValues, via one shared schemaDefaults module. Three boundaries measured and pinned in both directions: create-only (fixing a latent silent-write ObjectForm had been arming on edit forms), static-only (fixing ObjectForm's verbatim seeding of NOW()/current_user/CEL envelopes — a regression that would otherwise have shipped under this fix, given ~100 platform objects declare NOW()), and caller-values-win. defaultValue only is honored, not option-level default: true — measured against the server's applyFieldDefaults (one key is honored because one key is enforced; no UI-only second contract). Changeset patch + README/guide docs.
Review notes: the card's mechanism hypothesis (and my dispatch assumption) was refuted with evidence — ObjectForm was never on the create dialog's path; ModalForm and four sibling containers each carried their own schema-blind create branch. The dev fixed at the true producer with one module instead of five copies — acknowledged openly here as the process working. Test-first: the red baseline (9 failed on origin/main) IS the reverse verification, plus a targeted gate-removal check that flips exactly one assertion (and the report explains why the status: null variant would have been green for an empty reason — that level of test skepticism is exactly right). Consumer sweep over plugin-view/plugin-designer/app-shell: 3056 green. 11 files all in packages/plugin-form + docs; GridField* and app-shell untouched. All 20 checks completed: 18 success / 2 skipped / 0 failures (Lint, Type Check, 4 shards individually verified).
Out-of-scope findings verified filed: #4069 (required + runtime-token default is unsubmittable — one layer down, four dispositions listed; triaged next) and objectstack#7246 (SelectOption.default declared-but-unenforced, finding — the one consumer is a lint heuristic that draws a build-breaking conclusion from an unenforced declaration; ADR-0049 territory for the framework triage seat).
Landing next: flipping ready and driving to MERGED.
Activity
yinlianghui commentedon Aug 10, 2026
Claim: PM loop round 2 (objectui whole-repo seat — queue fill per the maintainer's 2026-08-10 five-concurrent directive)
Session:
session_017Qqyix2QcnpUC9XeYVDzx3Branch:
claude/issue-4047-create-dialog-defaultsWorktree:
objectui-issue-4047Domain:
repo:objectui(whole-repo seat)File surface: the object create dialog's form-seeding path — expected around
packages/plugin-form/src/ObjectForm.tsx(default seeding exists at:825onorigin/main) and/or the app-shell create-dialog wiring that bypasses it; plus tests. ⛔ Region-exclusive vs the in-flight #3569 branch (baozhoutao): do not touchGridField/grid-column files inpackages/fields/packages/plugin-form. If the true producer of the defect is in another package than expected, report and fix at the producer (state where and why in the PR body) — do not patch a consumer.Container & model: M,
mode:subagent,model: opusSerial constraints cleared: no open claim or PR on the create-dialog path; #3569's pushed branches touch
GridField.tsx+ showcase fixtures (disjoint files, region declared above).Premise re-verified at dispatch: seeding logic exists (
ObjectForm.tsx:825readsfield.defaultValue); the card's server-side reading (create-omitting-field stores the default) makes this a console-only wiring defect, per the source triage (objectstack#5150).Generated by Claude Code
yinlianghui commentedon Aug 10, 2026
ACCEPT (objectui seat PM, session
session_017Qqyix2QcnpUC9XeYVDzx3, review of record) — PR #4068.What shipped: create forms across all six object-form containers now open with the schema's declared static
defaultValues, via one sharedschemaDefaultsmodule. Three boundaries measured and pinned in both directions: create-only (fixing a latent silent-write ObjectForm had been arming on edit forms), static-only (fixing ObjectForm's verbatim seeding ofNOW()/current_user/CEL envelopes — a regression that would otherwise have shipped under this fix, given ~100 platform objects declareNOW()), and caller-values-win.defaultValueonly is honored, not option-leveldefault: true— measured against the server'sapplyFieldDefaults(one key is honored because one key is enforced; no UI-only second contract). Changeset patch + README/guide docs.Review notes: the card's mechanism hypothesis (and my dispatch assumption) was refuted with evidence —
ObjectFormwas never on the create dialog's path;ModalFormand four sibling containers each carried their own schema-blind create branch. The dev fixed at the true producer with one module instead of five copies — acknowledged openly here as the process working. Test-first: the red baseline (9 failed on origin/main) IS the reverse verification, plus a targeted gate-removal check that flips exactly one assertion (and the report explains why thestatus: nullvariant would have been green for an empty reason — that level of test skepticism is exactly right). Consumer sweep over plugin-view/plugin-designer/app-shell: 3056 green. 11 files all inpackages/plugin-form+ docs;GridField*and app-shell untouched. All 20 checks completed: 18 success / 2 skipped / 0 failures (Lint, Type Check, 4 shards individually verified).Out-of-scope findings verified filed: #4069 (required + runtime-token default is unsubmittable — one layer down, four dispositions listed; triaged next) and objectstack#7246 (
SelectOption.defaultdeclared-but-unenforced,finding— the one consumer is a lint heuristic that draws a build-breaking conclusion from an unenforced declaration; ADR-0049 territory for the framework triage seat).Landing next: flipping ready and driving to MERGED.
Generated by Claude Code
fix(plugin-form): seed create forms from the object schema's declared…
feat(plugin-form): pre-fill the current_user defaultValue token on cr…