Repository navigation
Commit 5e2f386
fix(plugin-form): a sectioned object-form clears after a save on submitBehavior continue and resetOnSuccess (#27663)
domain:ui#2 · os-bill · session_01Utp6CY2n1JmZZKrHgtp9jC
<!-- claude-projects-attribution: {"github_login":"os-bill"} -->
_Requested by **Bill** · [project
thread](https://claude.ai/code/project/chan_016iMXWSZDzqWRWvWzdNo8wg?thread=cmsg_016iMXWSZDzqWRWvWzdNo8wgP6XkfpjCfyzzG2KwQPUZfy)_
Fixes #27602
Clause-②: no
Metadata-protocol: none
## 维护者速读
- 改了什么:`object-form`
的分组(sections)表单现在与平铺表单读同一条「保存后清空」规则,`submitBehavior: { kind: 'continue'
}` 或新建表单上的 `resetOnSuccess: true` 在保存后清空表单。
- 为什么改:分组表单原先不带这条规则,「保存并新增下一条」保存后仍留着上一条的值,用户再存一次就是一条近似重复记录;平铺表单早已正确。
- 风险与回滚:风险低,只是把平铺路径已有的同一表达式提成一个常量,两条路径共读;两个键都没声明的表单行为不变。回滚即 revert 本 PR。
- 先看:`ui/packages/plugin-form/src/ObjectForm.tsx` 的 `resetOnSubmit`
常量及分组路径 `form` 节点新加的一行;再看 `ObjectForm.resetOnSubmit-27602.test.tsx`。
- 两分钟验证:`pnpm --dir ui exec vitest run
packages/plugin-form/src/ObjectForm.resetOnSubmit-27602.test.tsx`,预期 6
个测试全绿(平铺、分组各 3 个)。
- 需要你做的:无,席位落地。
## What changes
`SimpleObjectForm` renders an `object-form` block through one of two
`form` nodes: the flat one, and the sectioned one (explicit `sections`,
or sections derived from the object's field groups). Only the flat node
carried `resetOnSubmit`, so a sectioned "save and add another" form kept
the saved record's values while the same declaration on a flat form
cleared it.
The rule is now one named const, `resetOnSubmit`, declared once beside
`formLayout` and read by both nodes:
```ts
const resetOnSubmit = schema.submitBehavior?.kind === 'continue'
|| (!schema.submitBehavior && schema.resetOnSuccess && schema.mode === 'create');
```
The expression is unchanged from the flat path's; the flat node now
reads the const instead of its own copy, and the sectioned node gains
the same key. Nothing else resets the form imperatively: the `continue`
arm of the submit-behaviour switch is a no-op whose comment already
defers to `resetOnSubmit`, and the form renderer's single `form.reset()`
call after a successful submit is the only reader.
Changeset: `@object-ui/plugin-form` patch.
## Tests
`ui/packages/plugin-form/src/ObjectForm.resetOnSubmit-27602.test.tsx`
renders the same block flat and sectioned (`describe.each` over both
paths) and saves `name: 'Alpha'`, reading the field once the submit
button is enabled again (the form disables it for the whole submit,
reset included):
- `submitBehavior: { kind: 'continue' }` clears, on both paths;
- `resetOnSuccess: true` on a create form clears, on both paths;
- neither key declared keeps `Alpha`, on both paths.
**Ablation**, run once, on the committed fix (`97c6b181`), through
`scripts/ablation-replace.mjs`. The mutation deleted the sectioned
node's `resetOnSubmit,` line (anchor 1 → 0, blob `1fa7f7aa0930` →
`5c7ae6369dbf`). Result: the two sectioned clear cases went red and the
other four stayed green (`Tests 2 failed | 4 passed (6)`). The restore
was verified with blob == HEAD and an empty `git diff HEAD`. The test
imports `./ObjectForm` from source, so no build sits between the
mutation and the run.
## Acceptance notes
- Not reproduced in a browser; the defect and the fix are both measured
at the component layer, through the same `ObjectForm` the block
registers.
- Lint on the two touched files: 0 errors. The warnings are
`no-explicit-any`; the new test's four come from the same `as any`
schema and data-source casts its sibling
`ObjectForm.showReset-27247.test.tsx` uses.
## Verification
Local runs below were taken on head `57e13970`.
<details><summary>Targeted tests, type-check, lint</summary>
```text
pnpm --dir ui exec vitest run --maxWorkers=2 --reporter=verbose packages/plugin-form/src/ObjectForm.resetOnSubmit-27602.test.tsx packages/plugin-form/src/ObjectForm.submitBehavior.test.tsx packages/plugin-form/src/ObjectForm.showReset-27247.test.tsx packages/plugin-form/src/sectionedFormValues.test.tsx packages/components/src/renderers/form/__tests__/form-invalid-input-refuses-submit-27483.test.tsx :: exit 0
Test Files 5 passed (5) · Tests 30 passed (30) · the new file's 6 named, flat and sectioned
pnpm --filter @object-ui/plugin-form run type-check :: exit 0 (tsc --noEmit && tsc -p tsconfig.test.json)
pnpm --filter @object-ui/plugin-form exec eslint src/ObjectForm.tsx src/ObjectForm.resetOnSubmit-27602.test.tsx :: exit 0 (0 errors)
pnpm --dir ui run check:new-line-citations :: exit 0 (0 new citations)
pnpm --dir ui exec vitest run --maxWorkers=2 packages/plugin-form/ :: exit 0 (on 97c6b18, before the main merge: Test Files 212 passed (212) · Tests 2357 passed | 1 skipped)
```
The whole-package run is from the pre-merge commit. The merge brought no
change under `plugin-form`, so after it the five files above were run
again, including the form renderer test the merge added beside the
`resetOnSubmit` reader in `form.tsx`.
</details>
<details><summary>Derived gate families (dispatch-gates --commands,
reconciled with --ran)</summary>
```text
node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0
node scripts/check-adr-0087-registration.mjs --self-test :: exit 0
node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0
node scripts/check-closing-keyword-parity.mjs :: exit 0
node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0
node scripts/check-comment-mask-corpus.mjs :: exit 0
node scripts/check-empty-changeset.mjs --base origin/main :: exit 0
node scripts/check-empty-changeset.mjs --self-test :: exit 0
node scripts/check-sdui-manifest.mjs :: exit 0
node scripts/check-sdui-manifest.mjs --self-test :: exit 0
node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0
node scripts/release-pending-publish.mjs --self-test :: exit 0
pnpm --dir ui exec vitest run scripts/ :: exit 0
pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0
pnpm check:changeset-gate-self-tests :: exit 0
pnpm check:closed-ceremony-text :: exit 0
pnpm check:cross-package-test-inputs :: exit 0
pnpm check:dispatcher-error-vocabulary :: exit 0
pnpm check:driver-memory-census :: exit 0
pnpm check:engine-double-contract :: exit 0
pnpm check:gitlink-declared :: exit 0
pnpm check:nul-bytes :: exit 0
pnpm check:pm-changeset-deadline-census :: exit 0
pnpm check:published-files :: exit 0
pnpm check:query-options-erasure :: exit 0
pnpm check:refd-timer-probe :: exit 0
pnpm check:skill-identifier-liveness :: exit 0
pnpm check:test-source-alias :: exit 0
pnpm check:tier-file-adoption :: exit 0
pnpm check:type-check-coverage :: exit 0
pnpm check:type-check-debt :: exit 0
pnpm check:undeclared-dep-imports :: exit 0
pnpm check:watch-hint-literal :: exit 0
pnpm check:where-matcher :: exit 0
```
`node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack
--ran FILE` printed: `34 derived famil(ies) accounted for — 34 run, 0
NOT-MEASURED`. Every family CI runs beyond these (lint, type-check
lanes, Test UI, Build & E2E UI) is read from this PR's check-runs.
</details>
---
_Generated by [Claude
Code](https://claude.ai/code/session_01Utp6CY2n1JmZZKrHgtp9jC)_
Co-authored-by: Claude <noreply@anthropic.com>1 parent 9d29223 commit 5e2f386
3 files changed
Lines changed: 118 additions & 2 deletions
File tree
- .changeset
- ui/packages/plugin-form/src
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1548 | 1548 | | |
1549 | 1549 | | |
1550 | 1550 | | |
| 1551 | + | |
| 1552 | + | |
| 1553 | + | |
| 1554 | + | |
| 1555 | + | |
| 1556 | + | |
| 1557 | + | |
| 1558 | + | |
| 1559 | + | |
1551 | 1560 | | |
1552 | 1561 | | |
1553 | 1562 | | |
| |||
1745 | 1754 | | |
1746 | 1755 | | |
1747 | 1756 | | |
| 1757 | + | |
1748 | 1758 | | |
1749 | 1759 | | |
1750 | 1760 | | |
| |||
1909 | 1919 | | |
1910 | 1920 | | |
1911 | 1921 | | |
1912 | | - | |
1913 | | - | |
| 1922 | + | |
1914 | 1923 | | |
1915 | 1924 | | |
1916 | 1925 | | |
| |||
0 commit comments