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" }
]
}
| 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. |
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 field types are silently ignored.
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 value type field name, a relation type as a TypeFQN string, or "type" to restrict to a specific concrete subtype. |
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 field 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 type:
{ "name": "commons.country", "value": "nl" }
Subtype filter:
{ "name": "type", "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" }
]
}
]