Views
Views define how a list of objects is displayed as a table or column-based overview. A class can have multiple views — a default view, a relation view, and any number of named views.
Definition
{
"name": "openTasks",
"defaultView": false,
"relationView": false,
"defaultSort": "dueDate,desc",
"values": [
{ "name": "title" },
{ "name": "status", "dataType": "LIST", "list": "my-project.taskStatus" },
{ "type": "RELATION", "relatedClass": "commons.person" }
],
"filter": [
{ "name": "status", "value": "open" }
],
"navigateBehaviour": "OVERLAY_PAGE"
}
| Property | Type | Description |
|---|---|---|
name | string | Optional name. When set, this view is selected by name matching (e.g. in a VIEW layout item with the same name). |
defaultView | boolean | When true, used as the default for class dashboards and unnamed view embeds. |
relationView | boolean | When true, used for related-object list tabs (rendered by RELATED_VIEW layout items). |
defaultSort | string | Default sort order in REST API format: fieldName for ascending, fieldName,desc for descending. |
values | LayoutItem[] | Column definitions. Each entry is a FIELD or RELATION layout item. |
filter | ViewFilter[] | Static pre-filters automatically applied when this view is displayed. |
navigateBehaviour | NavigateBehaviour | Fallback used when an embedding VIEW or RELATED_VIEW layout item does not declare its own navigateBehaviour. See Navigate behaviour. |
Columns
The values array defines which columns are shown in the view. Each entry uses the same structure as Layout items — only FIELD and RELATION types are supported here.
"values": [
{ "name": "lastName" },
{ "name": "firstName" },
{ "type": "RELATION", "relatedClass": "commons.company" }
]
Column aggregations
Add "aggregate" to a column entry to show a totals row at the bottom of the table. The totals row recalculates whenever the active filter changes.
"values": [
{ "name": "description" },
{ "name": "units", "aggregate": "SUM" },
{ "name": "amount", "aggregate": "SUM" },
{ "name": "spentExternal", "aggregate": "AVG" }
]
| Value | Description |
|---|---|
"SUM" | Sum of all visible values. |
"AVG" | Average of all visible values. |
"COUNT" | Count of rows that have a value for this field. |
Only fields with data type INTEGER, DECIMAL, CURRENCY, or PERCENTAGE produce a result — other data types are silently ignored.
Platform properties as columns
Every object has three properties that the platform maintains itself. They can be used as columns without declaring a field; their names start with _, which a field name never does:
| Column | Shows |
|---|---|
_class | The object's concrete class, with its translated singular label (e.g. Sales dossier, Client agreement). |
_creationDate | When the object was created. |
_modificationDate | When the object was last changed. |
"values": [
{ "name": "title" },
{ "name": "_class" },
{ "name": "dueDate" },
{ "name": "_modificationDate" }
]
The _class column needs no manual LIST field or per-class formula. It mirrors the subclass filter syntax below: the same _class name can be used in filter to restrict the view to a specific concrete class instead of displaying it.
These columns are for display: a user cannot sort, filter or total on them.
Filters
filter defines static pre-filters that are always active for this view. These cannot be overridden by the user.
| Property | Description |
|---|---|
name | What to filter on: a field name, the qualified name of a relation's class, or _class to restrict to a specific concrete class. |
value | The filter value. Not required for EMPTY and NOT_EMPTY. |
operator | Filter operator. Omit to use the default (EQUALS). |
Operators
| Operator | Behavior | value | Applicable data types |
|---|---|---|---|
EQUALS (default) | Exact match. Case-insensitive for text fields. For LIST fields, value may be comma-separated to match any of the listed keys. | Required | All |
FROM | Greater than or equal (≥) | Required | DATE, DATETIME, INTEGER, DECIMAL, CURRENCY, PERCENTAGE |
TO | Less than or equal (≤) | Required | same |
STARTS_WITH | Prefix match (case-insensitive) | Required | TEXT, TEXTBLOCK, EMAIL; relations (matched by display name) |
EMPTY | Field has no value | Omit | All |
NOT_EMPTY | Field has a value | Omit | All |
Examples:
Exact match on a value field (default EQUALS):
{ "name": "status", "value": "active" }
Relation filter — only objects linked to a specific object of a relation's class:
{ "name": "commons.country", "value": "nl" }
Subclass filter:
{ "name": "_class", "value": "my-project.contractor" }
Multiple values on a LIST field (matches either key):
{ "name": "contractStatus", "value": "ACTIVE,PENDING" }
Date range — show only records with a due date in January 2026:
{ "name": "dueDate", "operator": "FROM", "value": "2026-01-01" },
{ "name": "dueDate", "operator": "TO", "value": "2026-01-31" }
Prefix match on a text field:
{ "name": "companyName", "operator": "STARTS_WITH", "value": "Acme" }
Only records where a field is not filled in:
{ "name": "closedAt", "operator": "EMPTY" }
Only records where a field has a value:
{ "name": "signedAt", "operator": "NOT_EMPTY" }
Negation
Excluding specific values (e.g. status != 'INACTIVE') is not supported. Use a boolean calculated field as a workaround:
{ "name": "contractActive", "formula": "contractStatus != 'INACTIVE'" }
Then filter on that field:
{ "name": "contractActive", "value": "true" }
Selecting views
Views are selected by the platform as follows:
- Class dashboards — the view with
defaultView: trueis used. VIEWlayout item — ifnameis set, the view with that name is used; otherwise the view withdefaultView: true.RELATED_VIEWlayout item — the view withrelationView: trueis used; ifnameis set, the view with that name is used instead.
Example
A class with two views — a default view for the list page, and a named compact view for embedding:
"views": [
{
"defaultView": true,
"defaultSort": "name",
"values": [
{ "name": "name" },
{ "name": "status" },
{ "name": "dueDate" },
{ "type": "RELATION", "relatedClass": "commons.person" }
]
},
{
"name": "compact",
"defaultSort": "dueDate",
"values": [
{ "name": "name" },
{ "name": "dueDate" }
],
"filter": [
{ "name": "status", "value": "open" }
]
}
]