Pre-alpha. No tagged release and no upgrade path between versions. Use for evaluation and development only, not production.
DevelopersPre-alpha

Views & menus

How XML views bind to model names, menu trees and when you need -u.

How UI is wired

Every screen a user opens is three XML pieces working together:

  1. Views: how one model looks (tree / form / kanban).
  2. Action: which model to open and in which view modes.
  3. Menu: where that action appears in the sidebar.

List the files in manifest.json -> data in that order (security -> actions -> views -> menus). Root element is always <sumeru><data>...</data></sumeru>.

Pre-alpha. Attribute names below match shipping sumeru / sumeru_addons XML. Do not assume attributes work unless listed here.

Quick map

GoalWriteNext
A list of records<view type="tree">Point an action's view_mode at tree
A detail screen<view type="form">Include form in view_mode
Cards board<view type="kanban"> + <templates>Add kanban to view_mode
Sidebar entry<menuitem action="..."/>Action id must load before the menu
Extend another module's UI<record model="sys.view"> + <xpath>Run -u on your module

<view>

Primary UI for one model. The engine stores the inner XML as arch on sys.view.

Syntax
xml
<view id="VIEW_XML_ID" model="dotted.model" type="tree|form|kanban|pivot" open="0"?>    ...fields / layout...</view>

id required

Syntax. id="view_my_module_tree". Letters, digits, _, ..

Effect. Stable XML id. Other modules inherit with ref="my_module.view_my_module_tree". Must be unique inside the module.

model required

Syntax. model="my.module". Exact string from Go ModelName().

Effect. Binds every nested <field name="..."/> to that model's schema. Wrong model -> missing columns / empty UI.

type required

Syntax. type="tree" | form | kanban | pivot.

Effect. Chooses the renderer. tree = list columns; form = sheet layout; kanban needs <templates>; pivot = read-only aggregation table (v1).

open optional

Syntax. On trees only: open="0".

Effect. Disables click-row -> open form. Use for read-only report lists (e.g. invoice analysis).

Example: read-only tree
xml
<view id="view_account_invoice_report_tree" model="account.invoice.report" type="tree" open="0">    <field name="partner_id" string="Customer"/>    <field name="amount_total" string="Total"/></view>

<field> in views

Inside <view>, each <field> maps one model field into the UI. Default widget comes from the field type; override with widget.

Syntax
xml
<field    name="field_name"    string="Label"?    widget="widget_key"?    placeholder="Hint..."?    options="{'key': 'value'}"?    readonly="1"?    invisible="1"?/>

name required

Syntax. name="active". Must match a key in Fields().

Effect. Selects which DB/ORM value to read and write. Unknown names are ignored or break render.

string optional

Syntax. string="Active".

Effect. Overrides the label from the model's String / field definition for this view only. Tree column header and form label use it.

widget optional

Syntax. widget="boolean_toggle" (see Widgets).

Effect. Swaps the default control (plain text/checkbox) for a specialised renderer. Wrong widget for the type -> odd or empty UI.

placeholder optional

Syntax. placeholder="e.g. SO001".

Effect. Grey hint inside empty inputs. Does not set a default value and is not stored.

options optional

Syntax. JSON-ish string: options="{'clickable': '1'}" (single quotes as in shipping XML).

Effect. Widget-specific knobs — statusbar clickable, priority mode:stars, many2one domain:[…]. See SWC widget catalog.

readonly optional

Syntax. readonly="1".

Effect. Field displays but the user cannot edit it in this view (e.g. computed timestamps, key prefixes).

required optional

Syntax. required="1".

Effect. Client-side required validation before save (merged with model-level Required from Go Fields()). See Field attributes.

invisible optional

Syntax. invisible="1".

Effect. Field stays in the arch (still loaded) but is not shown. Use sparingly in pre-alpha.

Example: labels and widgets
xml
<field name="name" string="Product" placeholder="Product Name..."/><field name="active" string="Active" widget="boolean_toggle"/><field name="key_prefix" string="Prefix" readonly="1"/>

<field> in <record>

Different job: set a column on a data row (groups, inherit views, defaults), not draw a widget.

Syntax
xml
<record id="XML_ID" model="some.model">    <field name="column">literal text</field>    <field name="rel_id" ref="other.module.xml_id"/>    <field name="m2m" eval="[(4, ref('some.group'))]"/>    <field name="arch" type="xml">...embedded xml...</field></record>

name

Effect. Target column on model.

ref

Syntax. ref="base.group_user" or same-module id.

Effect. Writes the database id of that XML record (Many2one-style links).

eval

Syntax. eval="[(4, ref('group_my_module_user'))]".

Effect. Evaluated expression. Common for M2M link commands like [(4, ref(...))].

type="xml"

Effect. Treats child nodes as XML arch (required for inherit arch blobs).

Widgets

Omit widget for the default control. Set it when you need a specific interaction.

boolean_toggle

Use on. Boolean fields. Effect. Switch control instead of a plain checkbox. Works in trees and forms.

snippet
xml
<field name="active" string="Active" widget="boolean_toggle"/>

handle

Use on. Integer sequence (or similar) columns in trees. Effect. Drag handle so users reorder rows; writes the sequence field.

snippet
xml
<view type="tree" ...>    <field name="sequence" widget="handle"/>    <field name="name"/></view>

statusbar

Use on. Selection / state fields, usually inside <header>. Effect. Shows stages as chips. With options="{'clickable': '1'}", users can click a stage to write the field (sale / purchase / CRM).

snippet
xml
<header>    <field name="state" widget="statusbar" options="{'clickable': '1'}"/></header>

selection

Use on. Selection or Many2one fields that should look like a dropdown. Effect. Select control (many2one uses the selection-style UI / cascade helpers where wired).

snippet
xml
<field name="country_id" string="Country" widget="selection"/>

email

Use on. Char email fields. Effect. Email-oriented input/display (company / partner forms).

snippet
xml
<field name="email" string="Email" widget="email"/>

priority

Use on. Priority / ranking selection or int. Effect. Compact priority control (stars / rank) instead of a raw number.

snippet
xml
<field name="priority" widget="priority"/>

mail_thread

Use on. A text / related field inside <chatter>. Effect. Hooks the activity / messages panel to that field.

snippet
xml
<chatter>    <field name="internal_notes" string="Communication" widget="mail_thread"/></chatter>

<button>

Place in <header> (or sheet). Click runs server-side logic named by name.

Syntax
xml
<button name="method_name" string="Label" type="object" class="sum_highlight"?/>

name required

Effect. Method to invoke on the current record (e.g. action_post, action_confirm). Must exist on the model / addon code path.

string required

Effect. Visible button label.

type required

Syntax. type="object" in all current samples.

Effect. Calls a method on the record. Not a URL, not a window action.

class optional

Syntax. class="sum_highlight" (or empty).

Effect. Visual emphasis for the primary action in the header.

Example: invoice header
xml
<header>    <button name="action_post" string="Post" type="object" class="sum_highlight"/>    <button name="action_register_payment" string="Register Payment" type="object"/>    <button name="action_cancel" string="Cancel" type="object"/>    <field name="state" widget="statusbar"/></header>

Form layout

Forms are nested containers. XML order is screen order.

<header>

Effect. Top chrome: buttons + statusbar. Keep workflow actions here.

<sheet>

Effect. Main body card. Put title, groups, notebooks inside.

<group>

Attributes. string="Address" (section title), colspan="2" (span full width).

Effect. Nested <group><group>...</group><group>...</group></group> builds a two-column grid.

<notebook> / <page>

Page attributes. string = tab label; name = optional technical tab id.

Effect. Tabs under the sheet. Only one page visible at a time.

<div class="sum_title">

Effect. Title block styling. Put the primary name field in an <h1>.

<chatter>

Effect. Hosts widget="mail_thread" beside/under the form (messages / log).

Example: groups and notebook
xml
<sheet>    <div class="sum_title">        <h1><field name="name" placeholder="Company legal name..."/></h1>    </div>    <group>        <group string="Identification">            <field name="vat" string="Tax ID"/>        </group>        <group string="Contact">            <field name="email" string="Email" widget="email"/>        </group>    </group>    <notebook>        <page string="Internal Notes" name="notes">            <field name="internal_notes"/>        </page>    </notebook></sheet><chatter>    <field name="internal_notes" string="Communication" widget="mail_thread"/></chatter>

<action>

A window action is what menus point at. It does not draw fields; it chooses the model and view modes.

Syntax
xml
<action    id="action_my_module"    type="window"    model="my.module"    name="My Module"    view_mode="tree,form,kanban">    <help>...optional empty-state HTML...</help></action>

id required

Effect. Target of <menuitem action="..."/>.

type required

Syntax. type="window".

Effect. Opens a model workspace (list/form/kanban switcher).

model required

Effect. Which model's views to load. Must match view model values.

name required

Effect. Title shown in the workspace chrome.

view_mode required

Syntax. Comma-separated, order = default tab order: tree,form,kanban.

Effect. Only listed modes appear. First mode is the landing view.

<help> optional

Effect. Empty-list placeholder. Class sum-view-nocontent-smiling-face is the usual styling hook.

Build a tree: root (app) -> section -> leaf with action.

Syntax
xml
<menuitem    id="menu_id"    name="Visible label"    sequence="10"    parent="parent_menu_id"?    action="action_xml_id"?    web_icon="shield"?    groups="module.group_xml_id"?/>

id required

Effect. XML id for parent="..." links.

name required

Effect. Sidebar label. Must be globally unique across addons (DB constraint on sys.menu.name). Prefer "My module records", not a second "Configuration".

sequence required in practice

Syntax. Integer, lower = higher in the list.

Effect. Sort order among siblings.

parent optional

Effect. Nest under another menu. Omit on app roots.

action optional

Effect. Leaf click opens that window action. Section nodes omit it.

web_icon optional

Syntax. Sprite key: shield, package, settings, users, file-text, shopping-cart, ...

Effect. Icon in the app switcher / sidebar (menu-icons.svg#i-KEY).

groups optional

Syntax. groups="account.group_account_invoice".

Effect. Menu is hidden unless the user belongs to that security group.

Example: menu tree
xml
<menuitem id="menu_my_module_root" name="My Module" sequence="20" web_icon="shield"/><menuitem id="menu_my_module_category" name="My module organization"    parent="menu_my_module_root" sequence="100"/><menuitem id="menu_my_module_action" name="My module records"    parent="menu_my_module_category" action="action_my_module" sequence="10"/>

End-to-end examples

Tree view

views/list_view.xml
xml
<?xml version="1.0" encoding="utf-8"?><sumeru>    <data>        <view id="view_my_module_tree" model="my.module" type="tree">            <field name="sequence" widget="handle"/>            <field name="name"/>            <field name="active" widget="boolean_toggle"/>        </view>    </data></sumeru>

Drag handle reorders via sequence; toggle flips active; click a row opens the form (unless open="0").

Form view

views/form_view.xml
xml
<?xml version="1.0" encoding="utf-8"?><sumeru>    <data>        <view id="view_my_module_form" model="my.module" type="form">            <header>                <button name="action_confirm" string="Confirm" type="object" class="sum_highlight"/>                <field name="active" widget="statusbar"/>            </header>            <sheet>                <div class="sum_title">                    <h1><field name="name" placeholder="Title..."/></h1>                </div>                <group>                    <group>                        <field name="sequence" string="Sequence"/>                    </group>                    <group>                        <field name="active" string="Active"/>                    </group>                </group>                <notebook>                    <page string="Description" name="description">                        <field name="description" placeholder="Internal notes..."/>                    </page>                </notebook>            </sheet>        </view>    </data></sumeru>

Kanban view

Declare preload fields, then the card template. t-name="kanban-box" is the card root.

views/kanban_view.xml
xml
<?xml version="1.0" encoding="utf-8"?><sumeru>    <data>        <view id="view_my_module_kanban" model="my.module" type="kanban">            <field name="name"/>            <templates>                <t t-name="kanban-box">                    <div class="sum-kanban-global-click">                        <div class="sum-kanban-details">                            <strong class="sum-kanban-record-title">                                <field name="name"/>                            </strong>                            <div><field name="description"/></div>                        </div>                    </div>                </t>            </templates>        </view>    </data></sumeru>

Pivot view

Set type="row", type="col", or type="measure" on nested <field> elements. The engine aggregates up to 500 rows from the action domain into a read-only HTML table. No CSV/PDF export or drill-down in v1.

views/pivot_view.xml
xml
<?xml version="1.0" encoding="utf-8"?><sumeru>    <data>        <view id="view_sale_order_pivot" model="sale.order" type="pivot">            <field name="partner_id" type="row"/>            <field name="date_order" type="col"/>            <field name="amount_total" type="measure"/>        </view>    </data></sumeru>

Include pivot in the window action view_mode, e.g. tree,form,pivot.

Action + menus

views/actions.xml
xml
<?xml version="1.0" encoding="utf-8"?><sumeru>    <data>        <action id="action_my_module" type="window" model="my.module"            name="My Module" view_mode="tree,form,kanban">            <help>                <p class="sum-view-nocontent-smiling-face">Create your first My Module!</p>            </help>        </action>    </data></sumeru>
views/menus.xml
xml
<?xml version="1.0" encoding="utf-8"?><sumeru>    <data>        <menuitem id="menu_my_module_root" name="My Module" sequence="20" web_icon="shield"/>        <menuitem id="menu_my_module_category" name="My module organization"            parent="menu_my_module_root" sequence="100"/>        <menuitem id="menu_my_module_action" name="My module records"            parent="menu_my_module_category" action="action_my_module" sequence="10"/>    </data></sumeru>

XML inheritance

Change another module's arch without copying the whole view.

Syntax
xml
<record id="view_..._inherit" model="sys.view">    <field name="name">technical.name</field>    <field name="model">dotted.model</field>    <field name="inherit_id" ref="module.parent_view_xml_id"/>    <field name="arch" type="xml">        <xpath expr="//field[@name='TARGET']" position="after|before|replace|inside">            ...nodes to insert or replace...        </xpath>    </field></record>

inherit_id + ref

Effect. Parent view to patch (must already exist).

expr

Syntax. Supported today: //field[@name='...'].

Effect. Locates the anchor field in the flattened arch.

position

Values. after | before | replace | inside.

Effect. Where the xpath body is applied relative to the match (inside appends before </view> in the flattened arch).

Example
xml
<record id="view_my_module_tree_inherit" model="sys.view">    <field name="name">my.module.tree.inherit</field>    <field name="model">my.module</field>    <field name="inherit_id" ref="my_module.view_my_module_tree"/>    <field name="arch" type="xml">        <xpath expr="//field[@name='name']" position="after">            <field name="description"/>        </xpath>    </field></record>

Narrow xpath. Implementation lives in core/engine/viewinherit. Exotic xpath expressions beyond simple field selectors will fail. Stick to //field[@name='...'].

Report exchange on views

Enable CSV/PDF download and bulk CSV import on list, kanban, and form views. Full engine reference: Report engine.

DeclarationAttributes
<report download="csv,pdf" upload="bulk" pdf_sizes="a4,legal,letter" modes="create,upsert"/>Child of <view> (recommended)
report_download, bulk_upload, pdf_sizes, bulk_modesView attributes (same meaning)
<widget type="report_download" formats="csv,pdf"/>Header widget on form or list
<widget type="bulk_upload" modes="create,upsert"/>Header widget for bulk import

When any capability is enabled, a Report toolbar appears. Pivot views do not support export in v1.

Kanban view attributes

On <view type="kanban"> (or nested <kanban> root):

default_group_by

Syntax. Field name, e.g. stage_id.

Effect. Columns grouped by that field. Falls back to group_by when unset.

group_by

Syntax. Field name.

Effect. Secondary grouping field when default_group_by is empty.

records_draggable

Syntax. 1 / true to enable drag between columns. Disable with false, 0, off, or no.

Effect. Drag-and-drop cards between kanban columns when enabled and user has write access.

quick_create

Syntax. Enable inline create in a grouped kanban column. Disable with 0, false, off, or no (CRM forecast uses quick_create="0").

Effect. Default on when the board is grouped. Quick-create merges action default_* values into the new record.

Profile photo and image fields

widget="image" on a binary or text field renders a file upload control without crop UI.

When a form has both an image field and a <div class="sum_title"> title block, the engine shows an avatar crop wizard (circular preview). Pan/zoom is stored in image_crop as JSON: {"x":0,"y":0,"zoom":1}. User profile forms in Settings use this path.

On kanban cards, image fields render full photos by default. Use widget="circle" for a circular avatar thumbnail.

Field groups attribute

On <field groups="module.group_xml_id">, the field is hidden when the signed-in user lacks that access group (same comma-separated group list as menu groups). Empty or missing groups means visible to everyone who can open the form.

Form validation and toasts

The live workspace is SWC. Toasts come from env.services.notification (top-right stack, close button, hover-pause, 6s auto-dismiss). See SWC notifications.

  • Client required check — empty required fields stay inline on the form (sum-flash). They are not a validation toast.
  • RPC / network errors — error toast. Successful save, delete, duplicate, and object buttons show a success toast unless the action returns {close}, {open}, or {redirect}.
  • Kanban — quick-create success toast; create/move RPC failures toast. Successful drag-move stays silent.
  • Removed HTTP — do not POST to /web/record/save (not registered). SWC uses JSON-RPC and env.services.notification. See HTTP routes.

When to run -u

After any XML / CSV change: update the module so data sync reloads arch and menus.

Terminal
shell
go run . -- -c sumeru.conf -u my_module --stop-after-initmake run

What not to do

  • Root element must be <sumeru> only — not legacy ERP root tags.
  • Do not reuse menu name values across addons.
  • Do not list menus before actions in data.
  • Do not invent widget names; use the SWC widget catalog.
  • Do not skip -u after XML edits and wonder why the UI is stale.

SWC reference

Next step

Configure export and import ACL in Report engine, then gate menus in Security & access.