Widgets
Widgets control how fields are displayed and edited.
Default Widget Mapping
Section titled “Default Widget Mapping”When no explicit widget is specified in a view, the system automatically selects a default widget based on the field type:
| Field Type | Default Widget |
|---|---|
| Char | TextInput |
| Text | TextArea |
| Integer | NumberInput |
| Float | NumberInput |
| Monetary | Monetary |
| Boolean | Checkbox |
| Date | DatePickerInput |
| Datetime | DateTimePicker |
| Selection | SelectCombo |
| ManyToOne | DataCombo |
| OneToOne | DataCombo |
| ManyToMany | MultiCombo |
| OneToMany | List |
| File | FileUpload |
| JSON | JSONInput |
You can override the default by specifying a widget property:
{ "type": "field", "name": "status", "properties": { "widget": "Badge" }}Widget Mode Support
Section titled “Widget Mode Support”Widgets support different view modes (Form, List, FormList, Kanban, Display). When a widget is used in an unsupported mode, it falls back to display mode if available, or shows “Unsupported widget”.
| Widget | Form | List | FormList | Kanban | Display | Notes |
|---|---|---|---|---|---|---|
| Dashboard Widgets | ||||||
| Card | ✓ | - | - | - | ✓ | KPI/metric display |
| CompactList | ✓ | - | - | ✓ | ✓ | Summary table/list |
| Display Widgets | ||||||
| LinkedRecords | ✓ | - | - | - | ✓ | Related records with actions |
| Avatar | ✓ | ✓ | ✓ | ✓ | ✓ | |
| Badge | ✓ | ✓ | ✓ | ✓ | ✓ | |
| BarChart | ✓ | - | - | ✓ | ✓ | Not suitable for inline table cells |
| AreaChart | ✓ | - | - | ✓ | ✓ | Not suitable for inline table cells |
| Sparkline | ✓ | ✓ | ✓ | ✓ | ✓ | Compact, suitable for inline |
| Image | ✓ | ✓ | ✓ | ✓ | ✓ | |
| ProgressBar | ✓ | ✓ | ✓ | ✓ | ✓ | |
| Rating | ✓ | ✓ | ✓ | ✓ | ✓ | |
| StatusBar | ✓ | - | - | - | - | Top-level form element type: statusbar, not a field widget |
| Input Widgets | ||||||
| TextInput | ✓ | ✓ | ✓ | ✓ | ✓ | |
| TextArea | ✓ | ✓ | ✓ | ✓ | ✓ | |
| NumberInput | ✓ | ✓ | ✓ | ✓ | ✓ | |
| Monetary | ✓ | ✓ | ✓ | ✓ | ✓ | |
| Checkbox | ✓ | ✓ | ✓ | ✓ | ✓ | |
| Switch | ✓ | ✓ | ✓ | ✓ | ✓ | |
| DatePickerInput | ✓ | ✓ | ✓ | ✓ | ✓ | |
| DateTimePicker | ✓ | ✓ | ✓ | ✓ | ✓ | |
| DateRangePicker | ✓ | - | - | - | ✓ | Form + Display only |
| TimeInput | ✓ | ✓ | ✓ | ✓ | ✓ | |
| ColorInput | ✓ | ✓ | ✓ | ✓ | ✓ | |
| RangeSlider | ✓ | - | - | ✓ | ✓ | Not suitable for inline editing |
| Slider | ✓ | - | - | ✓ | ✓ | Not suitable for inline editing |
| RichTextEditor | ✓ | - | - | - | ✓ | Form + Display only |
| FileInput | ✓ | ✓ | ✓ | ✓ | ✓ | |
| RadioCards | ✓ | ✓ | ✓ | ✓ | ✓ | |
| PasswordInput | ✓ | - | - | - | - | Form-only by design |
| JSONInput | ✓ | ✓ | ✓ | ✓ | ✓ | |
| FormulaInput | ✓ | ✓ | ✓ | ✓ | ✓ | Sandboxed formula editor with ƒx palette |
| MultiFileUpload | ✓ | ✓ | ✓ | ✓ | ✓ | Multiple file attachments |
| CodeEditor | ✓ | ✓ | ✓ | ✓ | ✓ | Syntax-highlighted code (CodeMirror) |
| Signature | ✓ | ✓ | ✓ | ✓ | ✓ | Canvas signature; stored as PNG data URL |
| Select Widgets | ||||||
| SelectCombo | ✓ | ✓ | ✓ | ✓ | ✓ | |
| Radio | ✓ | ✓ | ✓ | ✓ | ✓ | |
| DataCombo | ✓ | ✓ | ✓ | ✓ | ✓ | |
| AvatarCombo | ✓ | ✓ | ✓ | ✓ | ✓ | DataCombo with avatar display |
| MultiCombo | ✓ | ✓ | ✓ | ✓ | ✓ | |
| GroupAccessManager | ✓ | - | - | ✓ | ✓ | Complex UI, form-only editing |
| MultiOptionGroup | ✓ | - | - | ✓ | ✓ | Complex UI, form-only editing |
| Stepflow | ✓ | - | - | - | ✓ | Breadcrumb stepper for Selection state (form + display) |
| Layout Widgets | ||||||
| List | ✓ | - | - | - | ✓ | Embedded editable list (FormList) |
| Tags | ✓ | ✓ | - | ✓ | ✓ | |
| Title | ✓ | ✓ | ✓ | ✓ | ✓ | Section headers |
| Divider | ✓ | - | - | - | ✓ | Visual separator |
| Button | ✓ | - | - | ✓ | - | Action button |
| LinkButton | ✓ | ✓ | ✓ | ✓ | ✓ | Navigation button |
| Additional Input Widgets | ||||||
| PinInput | ✓ | - | - | - | - | Form-only, numeric PIN entry |
| SegmentedControl | ✓ | ✓ | ✓ | ✓ | ✓ | Button group selection |
| MonthPickerInput | ✓ | ✓ | ✓ | ✓ | ✓ | Month selector |
| YearPickerInput | ✓ | ✓ | ✓ | ✓ | ✓ | Year selector |
| ObjectFieldsInput | ✓ | - | - | - | ✓ | JSON object editor |
| FilterBuilder | ✓ | - | - | - | ✓ | Query filter builder |
| Additional Display Widgets | ||||||
| Icon | ✓ | - | - | ✓ | ✓ | Lucide icon display |
| BoxedIcon | - | - | - | ✓ | ✓ | Icon with background |
| WebsitePreview | ✓ | - | - | ✓ | ✓ | Website iframe preview |
Legend:
- ✓ = Supported
- - = Not supported (falls back to display mode or shows “Unsupported widget”)
Input Widgets
Section titled “Input Widgets”TextInput
Section titled “TextInput”Single-line text input.
{ "type": "field", "name": "name", "properties": { "widget": "TextInput", "placeholder": "Enter name", "size": "lg" }}| Property | Description |
|---|---|
placeholder | Placeholder text |
size | xs, sm, md, lg, xl |
disabled | Disable input |
TextArea
Section titled “TextArea”Multi-line text input.
{ "type": "field", "name": "description", "properties": { "widget": "TextArea", "rows": 4, "placeholder": "Enter description" }}RichTextEditor
Section titled “RichTextEditor”WYSIWYG HTML editor.
{ "type": "field", "name": "content", "properties": { "widget": "RichTextEditor" }}CodeEditor
Section titled “CodeEditor”Syntax-highlighted code editor (CodeMirror 6) for script/markup fields. Select the
language with the language prop — not mode (mode is the view render mode).
{ "type": "field", "name": "custom_js", "properties": { "widget": "CodeEditor", "language": "javascript" }}| Property | Description |
|---|---|
language | json, javascript, python, markdown, or html (defaults to plain) |
minHeight | Editor min height (e.g. "160px") |
Signature
Section titled “Signature”Canvas-based signature capture (no external dependency). The drawn signature is
stored on the field as a PNG data URL string; read-only and display modes render it
as an image. Back it with a Text/Char field.
{ "type": "field", "name": "signature", "properties": { "widget": "Signature", "label": "Customer Signature" }}NumberInput
Section titled “NumberInput”Numeric input with optional formatting.
{ "type": "field", "name": "price", "properties": { "widget": "NumberInput", "precision": 2, "prefix": "$", "min": 0 }}| Property | Description |
|---|---|
precision | Decimal places |
prefix | Static text before value (e.g., "$", "€") |
suffix | Static text after value (e.g., "%", "kg") |
min | Minimum value |
max | Maximum value |
:::tip Dynamic Prefix/Suffix
For dynamic values from related fields (e.g., displaying UOM name), define prefix_field or suffix_field on the model field definition instead:
# Model definitionquantity = Float(precision=3, suffix_field="uom__name")The model’s dynamic fields take priority over the view’s static values. See Prefix and Suffix Fields. :::
Monetary
Section titled “Monetary”The money widget — the default for Monetary fields and the right choice whenever a
value is currency. It formats the amount with the record’s currency symbol, position and
rounding, and is locale-aware. Bind the currency with currency_field (the model field
holding the currency object); in dashboard/display widgets the alias currencyField is
also accepted.
- type: field name: amount properties: widget: Monetary currency_field: currency| Property | Description |
|---|---|
currency_field | Sibling field holding the currency (symbol/position/rounding). Prefer setting currency_field on the model field so it applies everywhere. |
precision | Override decimal places (otherwise from the currency’s rounding) |
:::tip Model-side currency
For form fields bound to a model column, set currency_field on the field definition
itself rather than repeating it in every view. See
Prefix and Suffix Fields.
:::
JSONInput
Section titled “JSONInput”Raw JSON editor — the default widget for JSON fields. It pretty-prints the value,
validates on blur, and saves the parsed object (not the string). Display and kanban
modes render the JSON read-only in a code block.
- type: field name: procurement_trace properties: widget: JSONInput readonly: true visible: Q(procurement_trace__isnotnull=True)| Property | Description |
|---|---|
minRows | Minimum textarea rows in form mode (default: 4) |
maxRows | Maximum textarea rows before scrolling (default: 12) |
placeholder | Placeholder text |
For an object editor with typed key/value rows instead of raw text, see
ObjectFieldsInput.
FormulaInput
Section titled “FormulaInput”A single-line editor for safe-eval formula fields (e.g. salary components, financial
report lines). It surfaces the expression vocabulary through a ƒx palette listing
the available variables and functions, and validates client-side (no string literals,
only known names) so mistakes surface before save.
The variable namespace comes from one of two sources:
# Server namespace: a no-arg classmethod returning {variables, functions}- type: field name: formula properties: widget: FormulaInput label: Formula namespaceModel: Payslip namespaceMethod: formula_namespace# Sibling-row namespace: variables are the live values of a peer grid column- type: field name: formula properties: widget: FormulaInput label: Formula placeholder: e.g. revenue - cogs variablesFromField: code # peer column supplying variable names variableLabelField: label # peer column used as each variable's description| Property | Description |
|---|---|
namespaceModel | Model whose formula_namespace() supplies variables/functions (default Payslip) |
namespaceMethod | Classmethod name returning {variables, functions} (default formula_namespace) |
variablesFromField | Source variables from a sibling grid column instead of the server |
variableLabelField | Sibling column used as each variable’s description |
placeholder | Placeholder formula |
MultiFileUpload
Section titled “MultiFileUpload”Upload and manage multiple file attachments on one field. Form mode shows the uploader; list/kanban show a count badge; display shows the file-name badges.
- type: field name: attachments properties: widget: MultiFileUpload label: Attachments| Property | Description |
|---|---|
accept | Accepted MIME types / extensions (e.g. "image/*,.pdf") |
For a single file, use FileInput/ImageInput.
DatePickerInput
Section titled “DatePickerInput”Date selector.
{ "type": "field", "name": "due_date", "properties": { "widget": "DatePickerInput" }}DateTimePicker
Section titled “DateTimePicker”Date and time selector.
{ "type": "field", "name": "scheduled_at", "properties": { "widget": "DateTimePicker" }}Switch
Section titled “Switch”Boolean toggle.
{ "type": "field", "name": "active", "properties": { "widget": "Switch", "label": "Active" }}Checkbox
Section titled “Checkbox”Boolean checkbox.
{ "type": "field", "name": "terms_accepted", "properties": { "widget": "Checkbox", "label": "I accept the terms" }}Radio button group for Selection fields and ManyToOne fields.
Selection field example:
{ "type": "field", "name": "priority", "properties": { "widget": "Radio", "orientation": "horizontal" }}ManyToOne field example:
{ "type": "field", "name": "category", "properties": { "widget": "Radio", "orientation": "vertical", "filter": "Q(active__eq=true)" }}| Property | Description |
|---|---|
orientation | horizontal (default) or vertical |
size | xs (default), sm, md, lg |
filter | Q-expression to filter M2O options |
color | Mantine color for radio buttons |
For ManyToOne fields, all records from the related model are fetched and displayed as radio options.
RadioCards
Section titled “RadioCards”Card-based radio selection with icon, label, and description. Supports both Selection fields and ManyToOne fields. Ideal for visually rich option selection.
Selection field with custom options:
{ "type": "field", "name": "type", "properties": { "widget": "RadioCards", "columns": 3, "options": [ { "value": "Consumable", "label": "Consumable", "icon": "Package", "description": "Used once, not tracked in inventory" }, { "value": "Stockable", "label": "Stockable", "icon": "Warehouse", "description": "Tracked in inventory with stock levels" }, { "value": "Service", "label": "Service", "icon": "Wrench", "description": "Non-physical service offering" } ] }}ManyToOne field example:
{ "type": "field", "name": "product_category", "properties": { "widget": "RadioCards", "icon": "Folder", "columns": 2, "filter": "Q(parent__isnull=true)" }}| Property | Description |
|---|---|
options | Array of option objects with value, label, icon, description |
columns | Number of columns for grid layout |
size | sm, md (default), lg |
icon | Fallback icon for all cards (required for M2O, optional for Selection) |
filter | Q-expression to filter M2O options |
color | Mantine color for badges in display modes |
Option object properties (for Selection fields):
| Property | Required | Description |
|---|---|---|
value | Yes | The value stored when selected |
label | No | Display label (defaults to value) |
icon | No | Lucide icon name (overrides fallback icon prop) |
description | No | Description text below label |
Notes:
- For Selection fields: options can be provided explicitly or derived from the field’s choices
- For ManyToOne fields: all records are fetched from the related model. Use
iconprop to set a fallback icon (defaults toIconCircleif not provided) - Both widgets support
groups,visible, andreadonlyproperties (handled at the form level)
SelectCombo
Section titled “SelectCombo”Selection dropdown for Selection fields.
{ "type": "field", "name": "status", "properties": { "widget": "SelectCombo" }}DataCombo
Section titled “DataCombo”Dropdown for ManyToOne fields.
{ "type": "field", "name": "customer", "properties": { "widget": "DataCombo", "filter": "Q(is_customer=True)" }}| Property | Description |
|---|---|
filter | Domain filter for options |
create | Allow creating new records |
context | Default values for “Create & Edit” (see Field-Level Context) |
Dynamic Field References in Filters
Section titled “Dynamic Field References in Filters”Filters can reference current form/row values using three patterns:
| Pattern | Description | Example |
|---|---|---|
[field] | Bracketed field reference | Q(company__in=[company]) |
[field__nested] | Bracketed nested traversal | Q(currency__eq=[contact__company]) |
_parent.field | Parent form field (in line items) | Q(company__in=[_parent.company]) |
_parent.field__nested | Parent’s nested field | Q(currency__eq=[_parent.contact__company]) |
field__nested | Unbracketed (after =) | Q(currency__eq=contact__company) |
:::warning Depth Limitation Right-side field references are limited to 2 levels of relation traversal due to backend serialization depth. The install/update process validates this and raises an error if exceeded.
| Depth | Example | Valid |
|---|---|---|
| 1 | contact__id | ✓ |
| 2 | contact__company__id | ✓ |
| 3 | contact__company__currency__id | ✗ Error |
Workarounds for deep nesting:
- Add a
related_fieldon the model to surface the value at a shallower level - Let the backend handle the filter (don’t use field references) :::
Example - Filter by parent form’s company (in invoice line items):
{ "type": "field", "name": "account", "properties": { "widget": "DataCombo", "filter": "Q(type__nin=['Receivable','Payable']) & (Q(companies__in=[_parent.company]) | Q(companies__isnull=True))" }}Example - Unbracketed field reference:
{ "type": "field", "name": "currency", "properties": { "widget": "DataCombo", "filter": "Q(id__eq=contact__company__currency)" }}AvatarCombo
Section titled “AvatarCombo”Dropdown for ManyToOne fields with avatar display. Similar to DataCombo but shows avatars alongside names in the dropdown options and selected value. Ideal for user/contact selection fields.
{ "type": "field", "name": "assigned_to", "properties": { "widget": "AvatarCombo", "avatarField": "avatar", "filter": "Q(active=True)" }}| Property | Type | Default | Description |
|---|---|---|---|
avatarField | String | "avatar" | Field name on related model containing avatar attachment ID |
avatarSize | String | "sm" | Avatar size (xs, sm, md, lg, xl) |
avatarRadius | String | "xl" | Avatar border radius |
filter | String | - | Domain filter for options (same as DataCombo) |
create | Boolean | false | Allow creating new records |
context | Object | - | Default values for “Create & Edit” |
Mode Behavior:
| Mode | Behavior |
|---|---|
| Form | Full AvatarCombo input with edit/readonly support |
| List | Avatar combo in edit mode, avatar + name display in view mode |
| FormList | Same as List |
| Kanban | Avatar + name display only (no input) |
| Display | Avatar + name with tooltip |
Example - User assignment with avatar:
{ "type": "field", "name": "user_id", "properties": { "widget": "AvatarCombo", "avatarField": "avatar", "avatarSize": "sm", "filter": "Q(active=True) & Q(groups__name__in=['Sales'])" }}Note: The avatarField should reference an attachment ID field (File type) on the related model. The widget fetches and caches avatar images automatically.
MultiCombo
Section titled “MultiCombo”Multi-select for ManyToMany fields.
{ "type": "field", "name": "tags", "properties": { "widget": "MultiCombo" }}| Property | Description |
|---|---|
filter | Domain filter for options |
create | Allow creating new records |
context | Default values for “Create & Edit” (see Field-Level Context) |
ImageInput
Section titled “ImageInput”Image upload field.
{ "type": "field", "name": "photo", "properties": { "widget": "ImageInput" }}ColorInput
Section titled “ColorInput”Color picker.
{ "type": "field", "name": "color", "properties": { "widget": "ColorInput" }}SegmentedControl
Section titled “SegmentedControl”Button group for mutually exclusive options. Works with Selection fields.
{ "type": "field", "name": "view_mode", "properties": { "widget": "SegmentedControl", "fullWidth": true }}| Property | Description |
|---|---|
fullWidth | Expand to fill container width |
size | xs, sm, md, lg, xl |
color | Mantine color for active segment |
MonthPickerInput
Section titled “MonthPickerInput”Month and year selector.
{ "type": "field", "name": "billing_month", "properties": { "widget": "MonthPickerInput" }}YearPickerInput
Section titled “YearPickerInput”Year selector.
{ "type": "field", "name": "fiscal_year", "properties": { "widget": "YearPickerInput" }}PinInput
Section titled “PinInput”Numeric PIN entry with individual character boxes.
{ "type": "field", "name": "verification_code", "properties": { "widget": "PinInput", "length": 6 }}| Property | Description |
|---|---|
length | Number of input boxes (default: 4) |
type | number (default) or alphanumeric |
mask | Hide input with asterisks |
Display Widgets
Section titled “Display Widgets”Plain text display.
{ "type": "field", "name": "name", "properties": { "widget": "Text", "fw": "600", "size": "lg", "c": "dimmed" }}| Property | Description |
|---|---|
fw | Font weight (400-900) |
size | xs, sm, md, lg, xl |
c | Color (dimmed, or hex) |
lineClamp | Max lines to show |
html | Render the value as raw HTML instead of plain text (e.g. a formatted address) |
Rendering raw HTML: set html: true to inject the field value as HTML — useful for
server-formatted blocks such as a multi-line address.
- type: field name: contact_address properties: widget: Text nolabel: true html: true c: dimmed size: smThere is no separate Html widget — raw-HTML display is the html prop on Text. The
HTML must come from trusted server-side rendering.
Colored badge.
{ "type": "field", "name": "status", "properties": { "widget": "Badge", "variant": "dot", "size": "sm", "colors": { "draft": "gray", "active": "green", "archived": "red" } }}| Property | Description |
|---|---|
variant | filled, outline, dot |
size | Badge size |
colors | Color mapping by value |
Display multiple tags.
{ "type": "field", "name": "tags", "properties": { "widget": "Tags", "size": "sm" }}Avatar
Section titled “Avatar”Display-only avatar widget with automatic image fetching. Shows user initials when no image is available.
{ "type": "field", "name": "user_id", "properties": { "widget": "Avatar", "avatarField": "avatar", "size": "md" }}| Property | Type | Default | Description |
|---|---|---|---|
avatarField | String | "avatar" | Field name on value object containing attachment ID |
size | String | "md" | Avatar size (xs, sm, md, lg, xl) |
radius | String | "xl" | Border radius |
color | String | "initials" | Background color for initials |
How it works:
The widget automatically fetches avatar images when:
- Value is an object with an attachment ID field (specified by
avatarField) - Value itself is an attachment ID (number)
- Fallback fields:
image,avataron the value object
Example - Display user avatar in a list:
{ "type": "field", "name": "assigned_to", "properties": { "widget": "Avatar", "avatarField": "avatar", "size": "sm" }}Display image.
{ "type": "field", "name": "image", "properties": { "widget": "Image", "h": 100, "w": 100, "fit": "cover" }}| Property | Description |
|---|---|
h | Height in pixels |
w | Width in pixels |
fit | cover, contain, fill |
Rating
Section titled “Rating”Star rating display.
{ "type": "field", "name": "rating", "properties": { "widget": "Rating", "count": 5 }}Display a Lucide icon.
{ "type": "field", "name": "icon_name", "properties": { "widget": "Icon", "size": 24, "color": "blue" }}| Property | Description |
|---|---|
size | Icon size in pixels |
color | Mantine color (e.g., blue, red.6) |
BoxedIcon
Section titled “BoxedIcon”Icon with colored background box.
{ "type": "field", "name": "icon_name", "properties": { "widget": "BoxedIcon", "size": 40, "color": "teal" }}| Property | Description |
|---|---|
size | Box size in pixels |
color | Mantine color for background |
ProgressBar
Section titled “ProgressBar”Progress bar display.
{ "type": "field", "name": "completion", "properties": { "widget": "ProgressBar", "color": "blue", "size": "md" }}| Property | Description |
|---|---|
color | Mantine color |
size | xs, sm, md, lg, xl |
striped | Show striped pattern |
animated | Animate the stripes |
Stepflow
Section titled “Stepflow”A breadcrumb-style stepper for a Selection state field — renders the choices as
Draft › Sent › Order › Done with the current value highlighted as a pill. It is a
top-level form element (type: stepflow, bound by name) placed near the status
ribbon, not buried in the grid. Read-only by default.
- type: stepflow name: state properties: hideInactive: - Cancelled| Property | Description |
|---|---|
hideInactive | List of state values to hide unless they are the current value (e.g. terminal states like Cancelled) |
The steps are derived automatically from the bound Selection field’s choices, so they
are the human-readable state labels — no step list is configured in the view. Supported
in Form and Display modes only.
Dashboard Widgets
Section titled “Dashboard Widgets”Dashboard widgets display KPIs, metrics, and summary data in form views. They support locale-aware number formatting using the user’s language settings.
:::info Display Widget Properties
Dashboard and display widgets (Card, CompactList, Charts) can specify currencyField directly in view properties because they display arbitrary data rather than mapping to model fields. For form fields bound to model definitions, use currency_field on the model instead. The prefix and suffix properties are always static strings.
:::
Displays a KPI/metric card with value, label, icon, and optional click action. Perfect for dashboard overviews.
{ "type": "field", "name": "total_revenue", "properties": { "widget": "Card", "label": "Total Revenue", "icon": "DollarSign", "color": "green", "format": "currency", "currencyField": "currency", "method": "action_view_revenue_details" }}| Property | Type | Default | Description |
|---|---|---|---|
label | String | "Value" | Display label above the value |
icon | String | "ChartBar" | Lucide icon name |
color | String | "blue" | Mantine color for icon/hover |
format | String | - | Format type: currency, number, integer, percent |
currencyField | String | - | Field path containing currency object (e.g., "currency", "company__currency") |
prefix | String | - | Static prefix text (e.g., "$", "€") |
suffix | String | - | Static suffix text (e.g., "%", "kg") |
precision | Number/String | 2 | Decimal places (static int) or field path (e.g., "uom__rounding") |
method | String | - | Action method to call when clicked |
CompactList
Section titled “CompactList”A compact table/list for displaying summary data like top customers, recent items, etc.
Model field:
top_customers = JSON(description="Top Customers", default=[])View usage:
{ "type": "field", "name": "top_customers", "properties": { "widget": "CompactList", "currencyField": "currency", "columns": [ { "field": "name", "label": "Customer", "flex": 2, "bold": true }, { "field": "count", "label": "Orders", "align": "center", "format": "integer" }, { "field": "amount", "label": "Total", "format": "currency", "color": "blue", "bold": true } ], "method": "action_view_customer" }}CompactList Properties:
| Property | Type | Default | Description |
|---|---|---|---|
columns | Array | Auto-generated | Column definitions (see below) |
currencyField | String | - | Field path containing currency object (e.g., "currency") |
prefix | String | - | Static prefix text (e.g., "$", "€") |
suffix | String | - | Static suffix text (e.g., "%", "kg") |
showHeader | Boolean | true | Show column headers |
emptyText | String | "No data available" | Text when list is empty |
method | String | - | Action method called on row click (receives item_id, item) |
Column Properties:
| Property | Type | Default | Description |
|---|---|---|---|
field | String | Required | Key in the data object |
label | String | Field name | Column header label |
format | String | "text" | text, currency, number, integer, percent, badge |
precision | Number/String | 2 | Decimal places (static int) or field path |
align | String | Auto | left, center, right (numbers default to right) |
flex | Number | 1 | Flex grow value |
width | String | - | Fixed column width |
color | String | - | Mantine color for text |
bold | Boolean | false | Bold text |
badgeColor | String | "gray" | Badge color when format is badge |
LinkedRecords
Section titled “LinkedRecords”Displays related records from a JSON field as cards with customizable layout and row actions. Useful for showing credit notes, related documents, or any list of linked items with action buttons.
Model field:
outstanding_credits = JSON(description="Outstanding Credits", default=[])View usage:
{ "type": "field", "name": "outstanding_credits", "properties": { "widget": "LinkedRecords", "title": "Available Credits", "content": [ { "type": "row", "content": [ { "type": "field", "name": "record_type", "properties": { "widget": "Badge", "color": "blue" } }, { "type": "field", "name": "number", "properties": { "fw": 600 } } ] }, { "type": "row", "content": [ { "type": "field", "name": "date", "properties": { "widget": "Date", "c": "dimmed" } }, { "type": "field", "name": "amount", "properties": { "widget": "Float", "currency": "currency" } } ] } ], "rowActions": [ { "icon": "ExternalLink", "method": "action_view", "tooltip": "View" }, { "icon": "Check", "method": "action_apply", "tooltip": "Apply", "confirm": "Apply this credit?" } ] }}LinkedRecords Properties:
| Property | Type | Default | Description |
|---|---|---|---|
title | String | - | Title displayed above the cards |
content | Array | Auto-generated | Layout definition with rows and fields |
rowActions | Array | [] | Action buttons for each card |
emptyText | String | "No records" | Text when list is empty |
hideWhenEmpty | Boolean | true | Hide widget when no records |
maxHeight | Number | - | Maximum height with scroll |
visible | Boolean/String | - | Visibility (Q-expression supported) |
readonly | Boolean/String | - | Hide actions when true |
groups | Array | - | Group-based access control |
Field Widgets in Content:
| Widget | Description |
|---|---|
Text | Default text display |
Badge | Colored badge (color property) |
Date | Formatted date |
Float | Formatted number with currency/prefix/suffix support |
Float Field Properties:
| Property | Description |
|---|---|
currency | Field name containing currency object (symbol, position, rounding) |
prefix | Static string or field path (e.g., "uom__name") |
suffix | Static string or field path |
precision | Number or field path for decimal places |
Row Action Properties:
| Property | Type | Description |
|---|---|---|
icon | String | Lucide icon name |
method | String | Action method to call (receives item_id, item) |
tooltip | String | Hover tooltip |
color | String | Icon color |
confirm | String | Confirmation message before action |
visible | String | Simple Q-expression for conditional visibility |
Chart Widgets
Section titled “Chart Widgets”Chart widgets display visual data representations. They work with JSON fields containing numeric arrays or structured data. All chart widgets support currency formatting and locale-aware number display.
Sparkline
Section titled “Sparkline”A compact inline chart perfect for showing trends in list views, kanban cards, and forms. Expects a JSON field with an array of numbers.
Model field:
sales_trend = JSON(description="Sales Trend", default=[])View usage:
{ "type": "field", "name": "sales_trend", "properties": { "widget": "Sparkline", "w": 120, "h": 24, "color": "blue", "curveType": "linear" }}| Property | Type | Default | Description |
|---|---|---|---|
w | Number | 100 | Width in pixels |
h | Number | 30 | Height in pixels |
color | String | "blue" | Mantine color (e.g., "teal", "red.6") |
curveType | String | "linear" | Curve type: linear, bump, natural, monotone, step |
strokeWidth | Number | 2 | Line stroke width |
fillOpacity | Number | 0.2 | Fill opacity (0-1) |
withGradient | Boolean | true | Use gradient fill |
trendColors | Object | - | Dynamic colors based on trend (see below) |
Trend Colors:
Use trendColors instead of color to change the chart color based on trend direction:
{ "type": "field", "name": "performance_data", "properties": { "widget": "Sparkline", "trendColors": { "positive": "teal", "negative": "red", "neutral": "gray" } }}- positive: Color when first value < last value (upward trend)
- negative: Color when first value > last value (downward trend)
- neutral: Color when first value = last value
BarChart
Section titled “BarChart”Bar chart for visualizing data with multiple series.
Model field:
monthly_data = JSON(description="Monthly Data", default=[])Data format:
[ {"month": "Jan", "sales": 100, "costs": 60}, {"month": "Feb", "sales": 120, "costs": 70}, {"month": "Mar", "sales": 90, "costs": 55}]View usage:
{ "type": "field", "name": "monthly_data", "properties": { "widget": "BarChart", "dataKey": "month", "h": 150, "currencyField": "currency" }}| Property | Type | Default | Description |
|---|---|---|---|
dataKey | String | Required | Field name for X-axis labels |
h | Number | 150 | Chart height in pixels |
currencyField | String | - | Field path containing currency object (e.g., "currency", "company__currency") |
prefix | String | - | Static prefix text (e.g., "$", "€") |
suffix | String | - | Static suffix text (e.g., "%", "kg") |
precision | Number/String | 2 | Decimal places (static int) or field path (e.g., "uom__rounding") |
The chart automatically generates series from all numeric fields in the data (excluding the dataKey field).
AreaChart
Section titled “AreaChart”Area chart with the same properties as BarChart.
{ "type": "field", "name": "trend_data", "properties": { "widget": "AreaChart", "dataKey": "date", "h": 200, "currencyField": "currency", "precision": 0 }}Values in chart tooltips are formatted using the user’s locale settings (decimal and thousands separators from Language profile).
Embedded View Widgets
Section titled “Embedded View Widgets”Embedded list view for OneToMany fields.
{ "type": "field", "name": "order_lines", "properties": { "widget": "List", "view": "order_line_list_view", "create": true, "delete": true, "context": { "form_identifier": "order_line_form_view", "default_qty": 1 } }}| Property | Description |
|---|---|
view | List view identifier to use |
create | Allow creating new records |
delete | Allow deleting records |
editable | true for inline editing, "modal" for modal editing |
limit | Maximum rows to display initially (default: 100). Shows “Load more” button when exceeded |
context | Default values and view references (see Field-Level Context) |
Pagination
Section titled “Pagination”For large OneToMany lists, use the limit property to enable client-side pagination:
{ "type": "field", "name": "order_lines", "properties": { "widget": "List", "editable": true, "limit": 50 }}When rows exceed the limit:
- Only the first
limitrows are displayed initially - A “Load X more (Y remaining)” button appears on the right
- Clicking the button loads the next batch of rows
- Pagination resets when navigating to a different record
Column Properties (Q-Expression Support)
Section titled “Column Properties (Q-Expression Support)”List columns (fields in the List view) support visible, readonly, required, and filter properties with Q-expression evaluation. These are evaluated per-row against the row data.
{ "type": "field", "name": "discount_amount", "properties": { "widget": "NumberInput", "visible": "Q(has_discount__eq=true)", "readonly": "Q(is_locked__eq=true)", "required": "Q(amount__gt=0)" }}Parent Data Access:
Use the _parent. prefix to access fields from the parent form (the form containing the List widget):
{ "type": "field", "name": "account", "properties": { "widget": "DataCombo", "filter": "Q(companies__in=[_parent.company]) | Q(companies__isnull=True)" }}Nested Field Access:
Use __ for traversing relationships (Django ORM style):
{ "type": "field", "name": "price", "properties": { "readonly": "Q(_parent.contact__company__locked__eq=true)" }}| Property | Type | Description |
|---|---|---|
visible | Boolean/String | Per-row visibility. false hides cell, Q-expression evaluated per-row |
readonly | Boolean/String | Per-row readonly. true or Q-expression |
required | Boolean/String | Per-row required. true or Q-expression |
filter | String | Q-expression filter for DataCombo/MultiCombo. Supports _parent. prefix |
Kanban
Section titled “Kanban”Embedded kanban view.
{ "type": "field", "name": "tasks", "properties": { "widget": "Kanban", "view": "task_kanban_view" }}Widget Property Reference
Section titled “Widget Property Reference”Common Properties
Section titled “Common Properties”| Property | Type | Description |
|---|---|---|
label | string | Field label |
nolabel | boolean | Hide label |
placeholder | string | Placeholder text |
size | string | Size variant |
visible | Boolean/String | Show/hide field. Can be false or Q-expression |
readonly | Boolean/String | Make field read-only. Can be true or Q-expression |
required | Boolean/String | Make field required. Can be true or Q-expression |
groups | Array | Group identifiers for access control |
Example with visibility/required:
{ "type": "field", "name": "price", "properties": { "widget": "NumberInput", "readonly": true, "required": "Q(type__eq='product')" }}See Element Properties for details.
Style Properties
Section titled “Style Properties”| Property | Type | Description |
|---|---|---|
fw | string/number | Font weight |
c | string | Text color |
mt | string | Margin top |
mb | string | Margin bottom |
style | object | Custom CSS |
Field-Level Context
Section titled “Field-Level Context”Field-level context allows you to pass default values and configuration to related record creation. This is useful for:
- Pre-populating fields when creating records from embedded lists
- Setting defaults when using “Create & Edit” in DataCombo/MultiCombo
- Specifying which form view to use for modal editing
Syntax
Section titled “Syntax”Use the context property with default_<fieldname> keys:
{ "type": "field", "name": "order_lines", "properties": { "widget": "List", "context": { "default_qty": 1, "default_uom": 5, "form_identifier": "order_line_form_view" } }}Supported Context Keys
Section titled “Supported Context Keys”| Key Pattern | Description |
|---|---|
default_<field> | Pre-populate field with value when creating new records |
form_identifier | Form view identifier for modal editing |
| Custom keys | Available via self._ctx in backend methods |
The full context object is passed to the backend and is accessible via self._ctx on model instances.
Examples
Section titled “Examples”List widget with defaults:
{ "type": "field", "name": "invoice_lines", "properties": { "widget": "List", "editable": true, "context": { "default_quantity": 1, "default_tax_included": true } }}DataCombo with Create & Edit defaults:
When users click “Create & Edit” in a DataCombo, the context values are passed to the new record form:
{ "type": "field", "name": "contact", "properties": { "widget": "DataCombo", "create": true, "context": { "default_is_customer": true, "default_company": 5 } }}Backend Access
Section titled “Backend Access”Context is passed to the backend when creating new records. The backend processes default_* in _default_get and makes the full context available via self._ctx:
class OrderLine(Model): async def _default_get(cls, context=None): """Called during record creation with field-level context.""" defaults = await super()._default_get(context) # default_* keys are automatically applied by the base method # Access custom context values for additional logic if context and context.get('custom_flag'): defaults['some_field'] = compute_default() return defaults
async def compute_some_field(self): """Access context in computed fields or any method.""" # self._ctx contains the full context passed from frontend if self._ctx.get('default_currency'): # Use context value passNext Steps
Section titled “Next Steps”- View Inheritance - Extending views
- Form Views - Using widgets in forms