|
| 1 | +--- |
| 2 | +title: Record Edit Modes |
| 3 | +description: Choose between modal and full-page record forms with the editMode metadata flag. |
| 4 | +--- |
| 5 | + |
| 6 | +# Record Edit Modes |
| 7 | + |
| 8 | +ObjectUI's default console shell (`@object-ui/app-shell`) supports two ways |
| 9 | +to render the create/edit form for a record: |
| 10 | + |
| 11 | +- **Modal** (default) — the form opens in an overlay dialog above the |
| 12 | + current view. Best for short forms, quick edits, and contextual data |
| 13 | + entry. |
| 14 | +- **Page** — the form takes over a full route. Best for long forms, |
| 15 | + multi-tab or wizard layouts, or anywhere you need a deep-linkable URL |
| 16 | + that survives a refresh and integrates with the browser back button. |
| 17 | + |
| 18 | +Both modes use the same `<ObjectForm>` pipeline under the hood, so all |
| 19 | +field types, sections, validations, and visibility expressions work |
| 20 | +identically in either mode. |
| 21 | + |
| 22 | +## Choosing a mode |
| 23 | + |
| 24 | +Set `editMode` on the object metadata: |
| 25 | + |
| 26 | +```jsonc |
| 27 | +// metadata/objects/account.json |
| 28 | +{ |
| 29 | + "name": "account", |
| 30 | + "label": "Account", |
| 31 | + "editMode": "page", // "modal" (default) | "page" |
| 32 | + "fields": { |
| 33 | + "name": { "type": "text", "label": "Name", "required": true }, |
| 34 | + "industry": { "type": "picklist", "label": "Industry" }, |
| 35 | + "owner": { "type": "lookup", "label": "Owner", "reference_to": "user" } |
| 36 | + } |
| 37 | +} |
| 38 | +``` |
| 39 | + |
| 40 | +Omitting `editMode` (or setting it to `"modal"`) keeps the existing |
| 41 | +behavior — clicking **Create** or **Edit** opens the global `ModalForm` |
| 42 | +overlay. |
| 43 | + |
| 44 | +## URL patterns |
| 45 | + |
| 46 | +When `editMode: "page"` is set, the console renders the form on a |
| 47 | +dedicated route under the active app: |
| 48 | + |
| 49 | +| Action | URL | |
| 50 | +|--------|-----| |
| 51 | +| Create | `/apps/:appName/:objectName/new` | |
| 52 | +| Edit | `/apps/:appName/:objectName/record/:recordId/edit` | |
| 53 | + |
| 54 | +Examples (for an app `sales` and an object `account`): |
| 55 | + |
| 56 | +- Create: `https://your-console.example/apps/sales/account/new` |
| 57 | +- Edit: `https://your-console.example/apps/sales/account/record/0015e000abcd/edit` |
| 58 | + |
| 59 | +These URLs are stable. Users can bookmark them, share them in chat, or |
| 60 | +refresh the page mid-edit (the form rehydrates from the URL `:recordId`). |
| 61 | + |
| 62 | +## Triggering the routes from JSON |
| 63 | + |
| 64 | +In addition to the implicit "click create/edit on a list" entry point, |
| 65 | +two declarative actions let you open the page-mode routes from any |
| 66 | +`<action:button>` in metadata: |
| 67 | + |
| 68 | +```jsonc |
| 69 | +{ |
| 70 | + "type": "action:button", |
| 71 | + "label": "New Account", |
| 72 | + "icon": "plus", |
| 73 | + "action": { |
| 74 | + "action": "navigate_create", |
| 75 | + "params": { "objectName": "account" } |
| 76 | + } |
| 77 | +} |
| 78 | +``` |
| 79 | + |
| 80 | +```jsonc |
| 81 | +{ |
| 82 | + "type": "action:button", |
| 83 | + "label": "Edit", |
| 84 | + "icon": "pencil", |
| 85 | + "action": { |
| 86 | + "action": "navigate_edit", |
| 87 | + "params": { |
| 88 | + "objectName": "account", |
| 89 | + "recordId": "${record.id}" |
| 90 | + } |
| 91 | + } |
| 92 | +} |
| 93 | +``` |
| 94 | + |
| 95 | +When invoked from inside an `ObjectView`, the action context already |
| 96 | +carries the active `objectName`, so `objectName` may be omitted from the |
| 97 | +`params`: |
| 98 | + |
| 99 | +```jsonc |
| 100 | +{ |
| 101 | + "type": "action:button", |
| 102 | + "label": "New", |
| 103 | + "action": { "action": "navigate_create" } |
| 104 | +} |
| 105 | +``` |
| 106 | + |
| 107 | +## Behavior summary |
| 108 | + |
| 109 | +| Aspect | Modal | Page | |
| 110 | +|--------|-------|------| |
| 111 | +| Default | ✅ | — | |
| 112 | +| Deep-linkable URL | ❌ | ✅ | |
| 113 | +| Survives refresh | ❌ | ✅ | |
| 114 | +| Back button closes form | n/a | ✅ | |
| 115 | +| Best for | quick edits | long / multi-section forms | |
| 116 | + |
| 117 | +## Migrating an existing object |
| 118 | + |
| 119 | +The change is additive — existing apps continue to work unchanged. To |
| 120 | +migrate a single object to page mode: |
| 121 | + |
| 122 | +1. Add `"editMode": "page"` to the object metadata. |
| 123 | +2. (Optional) Adjust the form layout — page mode pairs well with |
| 124 | + `formType: "tabbed"` or `formType: "wizard"` for long forms. |
| 125 | +3. Reload the console. Existing **Create** / **Edit** entry points |
| 126 | + automatically route to the new pages; no UI code changes required. |
| 127 | + |
| 128 | +## See also |
| 129 | + |
| 130 | +- [`@object-ui/app-shell` README](https://www.objectui.org/docs/layout/app-shell) |
| 131 | +- [`ObjectForm` API](../plugins/plugin-form.md) |
| 132 | +- [Schema rendering](./schema-rendering.md) |
0 commit comments