ObjectUIObjectUI

Record Edit Modes

Choose between modal and full-page record forms with the editMode metadata flag.

Record Edit Modes

ObjectUI's default console shell (@object-ui/app-shell) supports two ways to render the create/edit form for a record:

  • Modal (default) — the form opens in an overlay dialog above the current view. Best for short forms, quick edits, and contextual data entry.
  • Page — the form takes over a full route. Best for long forms, multi-tab or wizard layouts, or anywhere you need a deep-linkable URL that survives a refresh and integrates with the browser back button.

Both modes use the same <ObjectForm> pipeline under the hood, so all field types, sections, validations, and visibility expressions work identically in either mode.

Choosing a mode

Set editMode on the object metadata:

// metadata/objects/account.json
{
  "name": "account",
  "label": "Account",
  "editMode": "page",       // "modal" (default) | "page"
  "fields": {
    "name":     { "type": "text",     "label": "Name", "required": true },
    "industry": { "type": "picklist", "label": "Industry" },
    "owner":    { "type": "lookup",   "label": "Owner", "reference_to": "user" }
  }
}

Omitting editMode (or setting it to "modal") keeps the existing behavior — clicking Create or Edit opens the global ModalForm overlay.

URL patterns

When editMode: "page" is set, the console renders the form on a dedicated route under the active app:

ActionURL
Create/apps/:appName/:objectName/new
Edit/apps/:appName/:objectName/record/:recordId/edit

Examples (for an app sales and an object account):

  • Create: https://your-console.example/apps/sales/account/new
  • Edit: https://your-console.example/apps/sales/account/record/0015e000abcd/edit

These URLs are stable. Users can bookmark them, share them in chat, or refresh the page mid-edit (the form rehydrates from the URL :recordId).

Triggering the routes from JSON

In addition to the implicit "click create/edit on a list" entry point, two declarative actions let you open the page-mode routes from an action:button in metadata. The handler name goes in actionType: that is the key the button renderer forwards to the action runner as the action's type, and the runner dispatches to the handler registered under it. Arguments go in a top-level params object:

{
  "type": "action:button",
  "label": "New Account",
  "icon":  "plus",
  "actionType": "navigate_create",
  "params": { "objectName": "account" }
}

navigate_edit additionally needs the record to open. params reaches the handler verbatim: template expressions such as ${record.id} are not evaluated inside params, and action:button does not inject the surrounding row, so a declared navigate_edit button carries a literal recordId:

{
  "type": "action:button",
  "label": "Edit",
  "icon":  "pencil",
  "actionType": "navigate_edit",
  "params": {
    "objectName": "account",
    "recordId":   "0015e000abcd"
  }
}

For a per-row Edit that follows the record under the cursor, use the list or detail view's built-in Edit entry point instead: under editMode: "page" it already routes to the same URL (see Migrating an existing object below).

When invoked from inside an ObjectView, the action context already carries the active objectName, so params may be omitted entirely:

{
  "type": "action:button",
  "label": "New",
  "actionType": "navigate_create"
}

Behavior summary

AspectModalPage
Default✅—
Deep-linkable URL❌✅
Survives refresh❌✅
Back button closes formn/a✅
Best forquick editslong / multi-section forms

Migrating an existing object

The change is additive — existing apps continue to work unchanged. To migrate a single object to page mode:

  1. Add "editMode": "page" to the object metadata.
  2. (Optional) Adjust the form layout — page mode pairs well with formType: "tabbed" or formType: "wizard" for long forms.
  3. Reload the console. Existing Create / Edit entry points automatically route to the new pages; no UI code changes required.

See also

On this page