Data Binding & Expressions
One of the most powerful features of Omni Designer is its seamless integration with your Odoo data model. Unlike cumbersome XML QWeb reports, you can browse and bind data visually.
The Data Tab
Section titled “The Data Tab”The Data tab in the sidebar shows the complete field schema of the model your report is based on (e.g., sale.order).
- Standard Fields: Name, Date, Amount, etc.
- Relational Fields (Many2one): Expand these (like
partner_id) to access fields of the related record (e.g.,partner_id.name,partner_id.email). - Collection Fields (One2many, Many2many): Represent lists of records (like
order_line). These are used with Section or Table components for repeating data.
Search & Navigate
Section titled “Search & Navigate”Use the search bar at the top of the Data tab to quickly filter and find fields. Click the collapse button to fold all expanded nodes back.
Drag and Drop Binding
Section titled “Drag and Drop Binding”- Simple Field: Drag a standard field (like
name) onto a blank area. Omni Designer reads the field type and creates aFieldcomponent bound to that data path. - Collection Field: If you drag a One2many/Many2many field (like
order_line), the designer can automatically create a repeatingSectioncontaining the inner fields.
Expression Syntax
Section titled “Expression Syntax”Behind the scenes, dynamic data is resolved using expressions. You can view or write these manually in the Property Panel under the element’s content property.
ReportBro Expressions ${ }
Section titled “ReportBro Expressions ${ }”The primary expression syntax uses ${ } delimiters:
- Simple field:
${name} - Deep path:
${partner_id.name} - Math:
${amount_total * 1.1} - Conditional:
${amount > 0 ? "Positive" : "Negative"}
Mustache Templates {{ }}
Section titled “Mustache Templates {{ }}”For more complex text where you want to mix static text with multiple dynamic values, you can use Mustache-style syntax with {{ }} delimiters:
Invoice #{{name}} {{partner_id.name}}
Built-in Functions
Section titled “Built-in Functions”The expression engine includes a rich library of built-in functions. You can use these in any expression field.
String Functions
Section titled “String Functions”| Function | Signature | Description |
|---|---|---|
len | len(s) | Returns the length of a string, list, or map |
upper | upper(s) | Converts string to uppercase |
lower | lower(s) | Converts string to lowercase |
str | str(x) | Converts value to string representation |
format | format(fmt, ...) | Formats a string with {0}, {1} placeholders |
strip | strip(s) | Removes leading and trailing whitespace |
replace | replace(s, old, new) | Replaces occurrences of a substring |
split | split(s, delimiter) | Splits string by delimiter |
join | join(separator, list) | Joins list elements with separator |
Math Functions
Section titled “Math Functions”| Function | Signature | Description |
|---|---|---|
round | round(x, n) | Rounds x to n decimal places |
abs | abs(x) | Returns absolute value |
floor | floor(x) | Largest integer ≤ x |
ceil | ceil(x) | Smallest integer ≥ x |
min | min(...) | Returns the smallest item |
max | max(...) | Returns the largest item |
sum | sum(list) | Returns sum of all items |
average | average(list) | Returns average of all items |
count | count(list) | Returns number of items in list |
Type Conversion
Section titled “Type Conversion”| Function | Signature | Description |
|---|---|---|
int | int(x) | Converts value to integer |
float | float(x) | Converts value to float |
bool | bool(x) | Converts value to boolean |
decimal | decimal(x) | Converts value to decimal number |
List Functions
Section titled “List Functions”| Function | Signature | Description |
|---|---|---|
sorted | sorted(list) | Returns a new sorted list |
reversed | reversed(seq) | Returns a reversed sequence |
any | any(list, x => expr) | True if predicate matches any item |
all | all(list, x => expr) | True if predicate matches all items |
countIf | countIf(list, x => expr) | Counts items where predicate is truthy |
first | first(list) | Returns first element (null if empty) |
last | last(list) | Returns last element (null if empty) |
Date & Time
Section titled “Date & Time”| Function | Signature | Description |
|---|---|---|
datetime.timedelta | datetime.timedelta(days=0, hours=0, ...) | Creates a duration for date arithmetic |
Operators
Section titled “Operators”| Operator | Description | Example |
|---|---|---|
+ - * / % | Arithmetic | 5 + 3 → 8 |
== != < > | Comparison | amount > 0 → true |
&& || ! | Logical AND, OR, NOT | a && b |
? : | Ternary (If-Else) | x > 0 ? "Yes" : "No" |
Context in Sections
Section titled “Context in Sections”When you use a Section component to iterate over a list of records (e.g., Data Source = order_line), the context inside that section changes.
Elements inside the section resolve expressions relative to the current row they are rendering:
- Inside an
order_lineSection,${name}evaluates to the line’s description, not the parent order’s name. - To reference the parent record from within a Section, use the full path from the root context.
Visibility and Conditional Logic
Section titled “Visibility and Conditional Logic”Every element has a Visibility property section. You can provide an expression here that must evaluate to a truthy value (true, non-zero, non-empty text) for the element to render.
- Example:
${state == 'sale'}the element only renders if the order is in “Sale” state. - Combine conditions:
${amount_total > 1000 && state == 'sale'} - This is ideal for conditionally hiding discount columns, tax summaries, or special disclaimers.
Dynamic Styles (Conditional Formatting)
Section titled “Dynamic Styles (Conditional Formatting)”Beyond visibility, each element supports Dynamic Styles conditional formatting rules that change the appearance of an element based on data.
For example:
- Turn the text red when
${amount < 0} - Add a yellow background when
${priority == 'urgent'}
Rules are managed through the Dynamic Styles section in the property panel. See the Components Reference for more details.