Custom Object Layouts
Layouts allow you to control how the properties of a Custom Object are displayed when viewing or editing instances of that object. Without a layout, all properties are displayed in a simple vertical list. With a layout, you can organize properties into sections, tabs, and multi-column arrangements.
Layout Settings
Each layout has the following settings:
Name |
A unique name for this layout (required). This name is shown to users when selecting a layout. |
Description |
An optional description explaining when this layout should be used. |
Ordinal |
Controls the display order of layouts. Lower numbers appear first. |
Active |
Only active layouts are available to users. Inactive layouts are hidden. |
Layout Assignments
Layouts can be assigned to specific users based on their role:
Allow All Users |
If set to Yes, any user that can view the project can use this layout. Role assignments are ignored. |
Allow Project Owner |
If set to Yes, the Project Owner can use this layout in addition to any assigned roles. |
Assigned Roles |
Select which Project Roles can use this layout. Users with these roles will see this layout as an option. |
When a user has access to multiple layouts, they can choose which one to use when viewing or editing custom object instances.
Layout JSON Format
The layout structure is defined using JSON. If no JSON is provided (empty), all properties are displayed in a simple vertical list.
Node Types
The layout JSON consists of nested nodes. Each node must have a type property. The available node types are:
Container Nodes (can contain other nodes):
VerticalLayout- Arranges children vertically, one below anotherHorizontalLayout- Arranges children horizontally in columnsSection- A collapsible section with a header labelTabs- Organizes children as tabbed panels
Leaf Nodes (display content):
Field- Displays a property fieldContent- Displays static HTML content (headings, text, separators, etc.)
Basic Structure
A simple vertical layout with three fields:
{
"type": "VerticalLayout",
"children": [
{"type": "Field", "fieldId": "Name"},
{"type": "Field", "fieldId": "Description"},
{"type": "Field", "fieldId": "Status"}
]
}
Field Node
Field nodes reference a property by name using the fieldId property:
{"type": "Field", "fieldId": "PropertyName"}
The fieldId must match the name of an active property definition for the custom object.
Fields not included in the layout will appear in an "Other Fields" section.
Content Node
Content nodes display static HTML content such as headings, help text, or separators.
Use the html property to specify the content:
{"type": "Content", "html": "<h4>Section Title</h4><p>Enter details below.</p>"}
Content nodes can also be used as spacers in horizontal layouts by using an empty html value:
{
"type": "HorizontalLayout",
"children": [
{"type": "Field", "fieldId": "FirstName", "columns": 5},
{"type": "Content", "html": "", "columns": 2},
{"type": "Field", "fieldId": "LastName", "columns": 5}
]
}
In a HorizontalLayout, Content nodes must include a columns property like other children.
Allowed HTML tags: b, div, hr, i, u, li, sup, br, ol, ul, font, small, h1, h2, h3, h4, p, a, span, sub, em, table, thead, tbody, th, tr, td.
For safety, HTML content is sanitized before display. Script tags and other potentially unsafe content will be removed.
Horizontal Layout
Use HorizontalLayout to arrange fields side by side. Each child must specify a columns value:
{
"type": "HorizontalLayout",
"children": [
{"type": "Field", "fieldId": "FirstName", "columns": 6},
{"type": "Field", "fieldId": "LastName", "columns": 6}
]
}
The total columns should not exceed 12. In this example, both fields take up half the width (6 + 6 = 12).
Section
Sections group related fields with a labeled header:
{
"type": "Section",
"label": "Contact Information",
"children": [
{"type": "Field", "fieldId": "Email"},
{"type": "Field", "fieldId": "Phone"}
]
}
Tabs
Tabs organize content into tabbed panels. Each child must have a label property for the tab title:
{
"type": "Tabs",
"children": [
{
"type": "VerticalLayout",
"label": "General",
"children": [
{"type": "Field", "fieldId": "Name"},
{"type": "Field", "fieldId": "Description"}
]
},
{
"type": "VerticalLayout",
"label": "Details",
"children": [
{"type": "Field", "fieldId": "Status"},
{"type": "Field", "fieldId": "Priority"}
]
}
]
}
Read-Only Fields
You can mark fields or entire containers as read-only by adding "read_only": true to a node.
Read-only fields are displayed with a lock icon and cannot be edited by the user, even if they
have edit permissions. This is useful for creating "review" layouts where most fields should be locked.
Making a single field read-only:
{"type": "Field", "fieldId": "ApprovedBy", "read_only": true}
Making all fields in a container read-only:
{
"type": "Section",
"label": "Approved Details",
"read_only": true,
"children": [
{"type": "Field", "fieldId": "ApprovedBy"},
{"type": "Field", "fieldId": "ApprovalDate"}
]
}
Overriding a parent's read-only setting:
A child node can explicitly set "read_only": false to override a parent container's read-only
setting. In this example, the "Status" field is editable even though the parent container is read-only:
{
"type": "VerticalLayout",
"read_only": true,
"children": [
{"type": "Field", "fieldId": "Name"},
{"type": "Field", "fieldId": "Description"},
{"type": "Field", "fieldId": "Status", "read_only": false}
]
}
The inheritance rules are:
If a node has
"read_only": true, it and all its descendants are read-only (unless overridden).If a node has
"read_only": false, it explicitly overrides any inherited read-only state.If a node does not have a
read_onlyproperty, it inherits from its parent.Content nodes do not support
read_only(they have no editable content).
In the layout editor preview, read-only fields are shown with a "Read-only" badge and a grey background.
Complex Example
This example combines multiple layout features including tabs, sections, horizontal layouts, and content:
{
"type": "Tabs",
"children": [
{
"type": "VerticalLayout",
"label": "Overview",
"children": [
{
"type": "Content",
"html": "<h4>Basic Information</h4><p>Enter the core details for this item.</p>"
},
{
"type": "HorizontalLayout",
"children": [
{"type": "Field", "fieldId": "Name", "columns": 8},
{"type": "Field", "fieldId": "Status", "columns": 4}
]
},
{"type": "Field", "fieldId": "Description"}
]
},
{
"type": "VerticalLayout",
"label": "Details",
"children": [
{
"type": "Section",
"label": "Dates",
"children": [
{
"type": "HorizontalLayout",
"children": [
{"type": "Field", "fieldId": "StartDate", "columns": 6},
{"type": "Field", "fieldId": "EndDate", "columns": 6}
]
}
]
},
{"type": "Content", "html": "<hr>"},
{
"type": "Section",
"label": "Assignment",
"children": [
{"type": "Field", "fieldId": "AssignedTo"},
{"type": "Field", "fieldId": "Priority"}
]
}
]
}
]
}
Validation Rules
The layout JSON is validated when saving:
The root must be a valid node type (typically
VerticalLayout,Section, orTabs)All
fieldIdvalues must match active property definition namesHorizontalLayoutchildren must havecolumnsvalues between 1 and 12HorizontalLayouttotal columns should not exceed 12Tabschildren must havelabelpropertiesread_only, if present, must be a boolean (trueorfalse)Contentnodes do not supportread_only
Live Preview
The layout editor provides a live preview that updates as you type. This helps you visualize the layout structure before saving. Fields that exist in the layout are shown with their names and types. Any fields not included in your layout are listed in the "Fields not in layout" section - these will appear in an "Other Fields" area when viewing custom object instances.