|
1 | 1 | --- |
2 | 2 | title: Forms (Public + Internal) |
3 | | -description: Render any FormView either publicly (anonymous, /f/:slug) or internally (authed operators, /forms/:name). The same metadata drives both, with URL prefill, configurable post-submit behavior, defaultDetailForm record binding, and declarative open-form actions. |
| 3 | +description: Render any FormView either publicly (anonymous, /f/:slug) or internally (authed operators, /forms/:name). The same metadata drives both, with URL prefill, configurable post-submit behavior, and declarative open-form actions. |
4 | 4 | --- |
5 | 5 |
|
6 | 6 | # Forms |
@@ -359,29 +359,26 @@ export default Action.create({ |
359 | 359 |
|
360 | 360 | Compared to `{ type: 'url', target: '/console/forms/quick_create' }`, the `'form'` variant is portable across runtimes — Studio/console/native shells can route it through their own form renderer instead of a raw navigation. |
361 | 361 |
|
362 | | -## 10. `defaultDetailForm` — bind a FormView to record detail |
363 | | - |
364 | | -Set `defaultDetailForm` on an object schema to pin the FormView used by the record-detail / edit screen. This is the Airtable Interface-form binding pattern. |
365 | | - |
366 | | -```ts |
367 | | -// hotcrm/src/objects/lead.object.ts |
368 | | -import { ObjectSchema } from '@objectstack/spec/data'; |
369 | | - |
370 | | -export default ObjectSchema.create({ |
371 | | - name: 'lead', |
372 | | - label: 'Lead', |
373 | | - defaultDetailForm: 'quick_create', // → views.formViews.quick_create |
374 | | - fields: { /* … */ }, |
375 | | -}); |
376 | | -``` |
377 | | - |
378 | | -Resolution order at runtime: |
379 | | - |
380 | | -1. `views.formViews[defaultDetailForm]` if set |
381 | | -2. `views.form` (the unnamed default form view) |
382 | | -3. Auto-generated grid layout from object fields |
383 | | - |
384 | | -The same FormView can therefore drive **three** experiences — public collection, internal quick-create, and record-detail editing — without duplicating layout metadata. |
| 362 | +## 10. Record detail is driven by semantic roles, not a form binding |
| 363 | + |
| 364 | +There is **no** object-level key that pins a FormView to the record-detail / |
| 365 | +edit screen (the once-documented `defaultDetailForm` was never implemented and |
| 366 | +has been removed from `ObjectSchema`). Record-detail rendering is derived from |
| 367 | +the object's **cross-surface semantic roles** (ADR-0085): |
| 368 | + |
| 369 | +- `nameField` — which field is the record's display name. |
| 370 | +- `highlightFields` — the most important fields (detail highlight strip, |
| 371 | + default list columns, cards). |
| 372 | +- `stageField` — the linear-lifecycle field behind the detail progress |
| 373 | + stepper (`false` suppresses detection). |
| 374 | +- `fieldGroups` + `Field.group` — semantic grouping, rendered identically on |
| 375 | + forms, modals, and detail pages. |
| 376 | + |
| 377 | +When a record page needs a bespoke layout beyond what the roles derive, assign |
| 378 | +the object a **custom Page schema** — that is the supported per-page |
| 379 | +customization path. FormViews remain the metadata for the two form |
| 380 | +experiences this guide covers: public collection (`/f/:slug`) and internal |
| 381 | +entry (`/forms/:name`). |
385 | 382 |
|
386 | 383 | ## 11. Security checklist (public mode) |
387 | 384 |
|
|
0 commit comments