AccountedPro - Layout JSON reference

For developers, and for anyone copying a view between sites. The JSON panel in the builder is read/write, so a layout can be pasted in whole.

A layout is one document — an Advanced List Layout whose layout_json holds the entire structure. It is validated on save against a schema, so a malformed layout is refused at the door rather than breaking a list at render time.

The shape

{
  "doctype_name": "Sales Order",
  "title": "Dispatch Board",
  "page_length": 20,
  "row_click": "expand",            // "open" | "expand" | "none"
  "auto_refresh_seconds": 300,
  "data_source": { "type": "standard" },
  "filter_tree": { … },              // the layout's own base condition
  "group_by": "status",
  "columns": [ … ],
  "tabs": [ … ],
  "cards": [ … ],
  "filters": [ … ],
  "header_buttons": [ … ],
  "expanded_row": { "blocks": [ … ] },
  "row_style": [ … ],
  "theme": { … }
}

Accepted values

Key Values
row_click expand, open, none
data_source.type standard, server_script
Element type field, virtual, static, button, chips, group, comments, image, related
Block type section, child_table, comments, related
Related display count, chips, sum, label
Action type server_script, whitelisted, set_value, url, route, new_doc
Card value.type count, sum, avg, payload_key
Filter type select, link, period, number_operator, text, date_range, check
mobile show, hide, only
Alignment left, center, right
Format kind currency, percent, float, int, date, datetime, relative, duration, text
Density compact, cosy, comfortable
View mode Table, Cards, Board
theme.group_header.order value, value_desc, count, list
Link hover underline, color, underline_color, highlight, none, ""

Conditions

Three shapes are accepted, and they mix:

{ "all": [ … ] }                                  // AND
{ "any": [ … ] }                                  // OR
{ "op": "and", "not": false, "children": [ … ] }  // what the builder writes

A leaf:

{
  "field": "currency",
  "op": "=",
  "value": "CAD",
  "not": false,
  "hops": [ { "field": "price_list", "doctype": "Price List" } ]
}

hops is the drill-down: each entry names a Link field and the DocType it lands on, and field is the field at the end of the chain. Ten levels maximum.

Operators: =, !=, >, >=, <, <=, in, not in, contains, not contains, is set, is not set, between, timespan.

Values may be literals, @me, or a relative date (today, -7d, start of month…).

A tab

{
  "id": "tab_mine",
  "label": "My Forms",
  "count": true,
  "condition": { "op": "and", "children": [ { "field": "owner", "op": "=", "value": "@me" } ] },
  "order_by": [ { "field": "date", "dir": "desc" } ],
  "columns_override": [ … ],
  "visible_if": { "roles": ["Sales Manager"], "condition": null }
}

order_by takes up to four entries, each asc or desc. A field may be a path (customer.customer_name).

Older layouts may carry filters — a flat list of [field, op, value] triples — instead of condition. Those still work and are rewritten as a condition the next time the tab is edited.

An element

{
  "id": "el_status",
  "type": "field",
  "fieldname": "status",
  "template": "{{ item_code }} × {{ qty }}",   // wins over fieldname
  "format": { "kind": "currency", "precision": 2 },
  "prefix": { "text": "MR-" },
  "empty_text": "—",
  "mobile": "show",
  "visible_if": { "roles": [], "condition": null },
  "style_rules": [
    { "when": { "field": "status", "op": "=", "value": "Overdue" },
      "style": { "pill": true, "bg": "red-100", "fg": "red-700" } },
    { "when": null, "style": { "pill": true, "bg": "gray-100" } }
  ]
}

Style rules are read in order and the first match wins; a rule with "when": null is the fallback and belongs last.

{
  "type": "related",
  "label": "Dispatch Orders",
  "related": {
    "target": "Dispatch Order",
    "link_field": "sales_order",
    "limit": 10,
    "condition": { … },                       // on the target
    "filters": [ ["price_list", "=", "{{ selling_price_list }}"] ]
  }
}

In filters, a value of {{ fieldname }} means "this row's value", and either side may be a path (price_list.currency).

What the validator enforces

  • Every id is unique across the layout — a tab cannot collide with a column.
  • Every fieldname exists on the DocType, unless the data source is a Server Script, in which case an unknown field is a warning rather than an error (the script may invent it).
  • Enumerated values must be from the lists above.
  • Numbers are bounded: widths, heights, font sizes, limit (1–100), order_by (max 4), hop depth (max 10).
  • A condition must be one of the three accepted shapes, with a known operator, and a value unless the operator is is set / is not set.

Errors block the save and name the path (columns[2].elements[0].fieldname). Warnings do not block — they appear next to the save.

Moving a layout between sites

Export writes the layout to a file; Import reads one back. The JSON panel is the same content if copying and pasting is easier. Only doctype_name has to match the target site — everything else is self-contained, though fields the target DocType does not have will fail validation on save, which is the point.

Discard
Save
This page has been updated since your last edit. Your draft may contain outdated content. Load Latest Version

On this page

Review Changes ← Back to Content
Message Status Space Raised By Last update on