36 KiB
DataGrid Formatting - User Guide
Introduction
The DataGrid Formatting system provides a powerful way to apply conditional styling and value formatting to your data grids. It allows you to create rich, readable data presentations with minimal code.
Key features:
- Apply styles (colors, fonts, decorations) based on cell values
- Format values for display (currencies, dates, percentages, text transformations)
- Create conditional rules that respond to data
- Reference other cells for cross-column/row comparisons
- Define formatting at multiple levels (cell, row, column, table, or globally)
Common use cases:
- Highlight negative values in financial reports
- Format currency and percentage values
- Color-code status indicators
- Display custom labels for enumerated values
- Apply different styles based on data thresholds
- Create visual hierarchies with conditional formatting
Quick Start
Here's a simple example to highlight negative values in red:
column amount:
style("error") if value < 0
format("EUR")
This creates a formatting rule that:
- Applies to all cells in the "amount" column
- Colors negative values with the "error" style (red background)
- Formats all values as Euro currency
Understanding Formatting
Formatting Levels
Formatting can be applied at five different levels, each with its own specificity:
| Level | Cells Targeted | Condition Evaluated On | Specificity |
|---|---|---|---|
| Cell | 1 specific cell | The cell value | Highest (1) |
| Row | All cells in the row | Each cell value | High (2) |
| Column | All cells in the column | Each cell value | Medium (3) |
| Table | All cells in a specific table | Each cell value | Low (4) |
| Tables | All cells in all tables (global) | Each cell value | Lowest (5) |
Visual hierarchy:
Cell (amount, 5) ← Highest priority
↓
Row 5 ← Overridden by cell
↓
Column amount ← Overridden by row and cell
↓
Table "products" ← Overridden by column, row, and cell
↓
Tables (global) ← Lowest priority, applies everywhere
How Rules Are Evaluated
Rules are processed from highest to lowest specificity. When multiple rules match:
- Cell-level rules win over all others
- Row-level rules win over column, table, and global rules
- Column-level rules win over table and global rules
- Table-level rules win over global rules
- Global rules apply only if no other rules match
Conflict Resolution
When multiple rules at the same level match a cell, style and formatter are resolved independently:
Style rules compete among themselves:
- Specificity = number of conditions in the rule (0 or 1)
- Higher specificity wins
- At equal specificity, last rule wins
Formatter rules compete among themselves:
- Same specificity logic as styles
- Resolved independently from styles
Style and formatter can fuse:
- If one rule provides the style and another provides the formatter, both are applied
- This allows separating concerns (e.g., unconditional formatting + conditional styling)
Example 1: Style competition
column amount:
style(color="gray") # Specificity: 0 (no condition)
style("error") if value < 0 # Specificity: 1
style("success", bold=True) if value > 0 # Specificity: 1
- For
value = -10: "error" style wins (specificity 1 > 0) - For
value = 50: "success" style wins (specificity 1 > 0) - For
value = 0: gray color applies (no other rules match)
Example 2: Style and formatter fusion
column amount:
format("EUR") # Unconditional formatter
style("error") if value < 0 # Conditional style
-
For
value = -100:- ✅ Style "error" applied (from conditional rule)
- ✅ Format "EUR" applied (from unconditional rule)
- Result:
-100,00 €with red background
-
For
value = 100:- ❌ No style (condition not met)
- ✅ Format "EUR" applied
- Result:
100,00 €with default style
Example 3: Multiple styles and formatters
column amount:
style("neutral") # Unconditional style
format("EUR") # Unconditional formatter
style("error") if value < 0 # Conditional style (higher specificity)
format.number(precision=0, suffix=" €") if value < 0 # Conditional formatter (higher specificity)
-
For
value = -5.67:- Style: "error" wins (specificity 1 > 0)
- Formatter: precision=0 wins (specificity 1 > 0)
- Result:
-6 €with red background
-
For
value = 1234.56:- Style: "neutral" applies (no conditional matches)
- Formatter: "EUR" applies (no conditional matches)
- Result:
1 234,56 €with neutral background
How Rules Work
A formatting rule consists of three optional parts:
[style(...)] [format(...)] [if <condition>]
Rules:
- At least one of
style()orformat()must be present conditionis optional- If a condition is present, the rule applies only when the condition is met
- Multiple rules can be defined for the same scope
Examples:
# Style only
style("error")
# Format only
format("EUR")
# Style + Format
style("error") format("EUR")
# With condition
style("error") if value < 0
# All combined
style("error") format("EUR") if value < 0
Writing Formatting Rules
Basic Syntax
A DSL document consists of scopes, each containing one or more rules:
<scope>:
<rule>
<rule>
...
<scope>:
<rule>
...
Scopes define which cells a rule applies to:
| Scope Syntax | Applies To | Example |
|---|---|---|
column <name>: |
All cells in the column | column amount: |
column "<name>": |
Column with spaces | column "total amount": |
row <index>: |
All cells in the row | row 0: |
cell (<col>, <row>): |
Single cell by coordinates | cell (amount, 3): |
cell <cell_id>: |
Single cell by ID | cell tcell_grid1-3-2: |
table "<name>": |
All cells in a specific table | table "products": |
tables: |
All cells in all tables | tables: |
Indentation and comments:
# This is a comment
column amount:
# Rules must be indented under their scope
style("error") if value < 0
format("EUR")
# Column names with spaces need quotes
column "total amount":
style("neutral", bold=True)
Styling Cells
The style() function applies visual formatting to cells.
Syntax:
style(<preset>)
style(<preset>, <options>)
style(<options>)
Available style presets (DaisyUI 5):
| Preset | Background | Text | Use Case |
|---|---|---|---|
primary |
Primary theme color | Primary content | Main highlights |
secondary |
Secondary theme color | Secondary content | Secondary highlights |
accent |
Accent theme color | Accent content | Accent highlights |
neutral |
Neutral theme color | Neutral content | Headers, totals |
info |
Info (blue) | Info content | Information |
success |
Success (green) | Success content | Positive values |
warning |
Warning (yellow) | Warning content | Warnings |
error |
Error (red) | Error content | Negative values, errors |
Style properties:
| Property | Type | Description | Example |
|---|---|---|---|
background_color |
string | Background color | "#ffeeee", "red", "var(--color-primary)" |
color |
string | Text color | "#cc0000", "white" |
bold |
boolean | Bold text | True, False |
italic |
boolean | Italic text | True, False |
underline |
boolean | Underlined text | True, False |
strikethrough |
boolean | Strikethrough text | True, False |
font_size |
string | Font size | "12px", "0.9em" |
Examples:
# Preset only
column status:
style("error")
# Preset with overrides
column total:
style("neutral", bold=True)
# Multiple properties
column name:
style("success", italic=True, underline=True)
# No preset, direct properties
column notes:
style(color="red", bold=True)
style(background_color="#ffeeee", color="#cc0000")
Formatting Values
The format() function transforms cell values for display without changing the underlying data.
Using presets:
# Preset only
format("EUR")
# Preset with overrides
format("EUR", precision=3)
Available formatter presets:
| Preset | Type | Description | Example Output |
|---|---|---|---|
EUR |
number | Euro currency | 1 234,56 € |
USD |
number | US Dollar | $1,234.56 |
percentage |
number | Percentage (×100) | 45.2% |
short_date |
date | DD/MM/YYYY | 29/01/2026 |
iso_date |
date | YYYY-MM-DD | 2026-01-29 |
yes_no |
boolean | Yes/No | Yes |
Using explicit types:
When not using a preset, specify the type explicitly:
format.number(precision=2, suffix=" €", thousands_sep=" ")
format.date(format="%d/%m/%Y")
format.boolean(true_value="Oui", false_value="Non")
format.text(max_length=50, ellipsis="...")
format.enum(source={"draft": "Draft", "published": "Published"})
format.constant(value="N/A")
Number Formatter
Formats numbers, currencies, and percentages.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
prefix |
string | "" |
Text before value (e.g., "$") |
suffix |
string | "" |
Text after value (e.g., " €", "%") |
thousands_sep |
string | "" |
Thousands separator (e.g., ",", " ") |
decimal_sep |
string | "." |
Decimal separator (e.g., ".", ",") |
precision |
int | 0 |
Number of decimal places |
multiplier |
number | 1 |
Multiply value before display (e.g., 100 for %) |
Examples:
# Euro currency
column amount:
format.number(suffix=" €", thousands_sep=" ", decimal_sep=",", precision=2)
# US Dollar
column price:
format.number(prefix="$", thousands_sep=",", precision=2)
# Percentage
column rate:
format.number(suffix="%", multiplier=100, precision=1)
# Large numbers with thousands separator
column population:
format.number(thousands_sep=",", precision=0)
Date Formatter
Formats dates and datetimes using strftime patterns.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
format |
string | "%Y-%m-%d" |
strftime format pattern |
Common format patterns:
| Pattern | Description | Example |
|---|---|---|
"%Y-%m-%d" |
ISO format | 2026-01-29 |
"%d/%m/%Y" |
European | 29/01/2026 |
"%m/%d/%Y" |
US format | 01/29/2026 |
"%d %b %Y" |
Short month | 29 Jan 2026 |
"%d %B %Y" |
Full month | 29 January 2026 |
"%Y-%m-%d %H:%M" |
With time | 2026-01-29 14:30 |
Examples:
# European format
column created_at:
format.date(format="%d/%m/%Y")
# Full date with month name
column updated_at:
format.date(format="%d %B %Y")
# ISO format with time
column timestamp:
format.date(format="%Y-%m-%d %H:%M:%S")
Boolean Formatter
Formats boolean and binary values.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
true_value |
string | "true" |
Display for true/1 |
false_value |
string | "false" |
Display for false/0 |
null_value |
string | "" |
Display for null/None |
Examples:
# Yes/No
column active:
format.boolean(true_value="Yes", false_value="No")
# Checked/Unchecked
column completed:
format.boolean(true_value="✓", false_value="✗")
# Custom labels
column status:
format.boolean(true_value="Enabled", false_value="Disabled", null_value="Unknown")
Text Formatter
Formats and transforms text values.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
transform |
string | - | "uppercase", "lowercase", "capitalize" |
max_length |
int | - | Truncate if exceeded |
ellipsis |
string | "..." |
Suffix when truncated |
Examples:
# Uppercase
column code:
format.text(transform="uppercase")
# Truncate long text
column description:
format.text(max_length=50, ellipsis="...")
# Capitalize first letter
column name:
format.text(transform="capitalize")
Enum Formatter
Maps values to display labels. Useful for status codes, categories, and dropdown lists.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
source |
object | - | Mapping or datagrid reference |
default |
string | "" |
Label for unknown values |
Source types:
Static mapping:
column status:
format.enum(
source={
"draft": "Draft",
"pending": "Pending Review",
"approved": "Approved",
"rejected": "Rejected"
},
default="Unknown"
)
From another DataGrid:
column category_id:
format.enum(
source={
"type": "datagrid",
"value": "categories_grid",
"value_column": "id",
"display_column": "name"
}
)
This looks up the category_id value in the "categories_grid", finds the matching row by "id", and displays the "name" column.
Constant Formatter
Displays a fixed value regardless of the cell's actual value. Useful for placeholder text or fixed labels.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
value |
string | - | The constant text to display |
Examples:
# Display "N/A" for all cells
column placeholder:
format.constant(value="N/A")
# Display fixed label
column type:
format.constant(value="Product")
# Combined with condition
column optional_field:
format.constant(value="—") if value isempty
Conditional Formatting
Conditions determine when a rule applies. They use the syntax:
if <left> <operator> <right>
if <operand> <unary_operator>
Comparison Operators
| Operator | Description | Example |
|---|---|---|
== |
Equal | value == 0 |
!= |
Not equal | value != "" |
< |
Less than | value < 0 |
<= |
Less or equal | value <= 100 |
> |
Greater than | value > 1000 |
>= |
Greater or equal | value >= 0 |
Examples:
column amount:
style("error") if value < 0
style("success") if value > 1000
style("warning") if value == 0
String Operators
| Operator | Description | Example |
|---|---|---|
contains |
String contains | value contains "error" |
startswith |
String starts with | value startswith "ERR" |
endswith |
String ends with | value endswith ".pdf" |
Examples:
column message:
style("error") if value contains "error"
style("info") if value startswith "INFO"
column filename:
style("accent") if value endswith ".pdf"
Note: String comparisons are case-insensitive by default. See "Case Sensitivity" below for case-sensitive matching.
List Operators
| Operator | Description | Example |
|---|---|---|
in |
Value in list | value in ["A", "B", "C"] |
between |
Value in range | value between 0 and 100 |
Examples:
column status:
style("success") if value in ["approved", "completed"]
style("warning") if value in ["pending", "review"]
column score:
style("error") if value between 0 and 30
style("warning") if value between 31 and 70
style("success") if value between 71 and 100
Empty and NaN Checks
| Operator | Description | Example |
|---|---|---|
isempty |
Is null or empty string | value isempty |
isnotempty |
Is not null or empty | value isnotempty |
isnan |
Is NaN (Not a Number) | value isnan |
Examples:
column notes:
style("neutral") if value isempty
format.constant(value="—") if value isempty
column calculation:
style("error") if value isnan
format.constant(value="Error") if value isnan
column required_field:
style("warning") if value isempty
Note: isempty checks for None or empty string (""). isnan specifically checks for invalid float values (NaN).
Cell References
References allow comparing a cell's value with values from other cells.
| Reference | Description | Example |
|---|---|---|
value |
Current cell value | value < 0 |
col.<name> |
Value from another column (same row) | value > col.budget |
col."<name>" |
Column with spaces | value > col."max amount" |
row.<index> |
Value from another row (same column) | value != row.0 |
cell.<col>-<row> |
Specific cell by coordinates | value == cell.status-0 |
Examples:
# Compare with another column
column actual:
style("error") if value > col.budget
style("warning") if value > col.budget * 0.9
# Compare with header row
column total:
style("neutral", bold=True) if value == row.0
# Compare with specific cell
column status:
style("success") if value == cell.status-0
Arithmetic in references:
You can perform simple arithmetic with column references:
column spending:
style("warning") if value > col.budget * 0.8
style("error") if value > col.budget * 1.1
Negation
Use not to negate any condition:
column status:
style("error") if not value in ["valid", "approved"]
style("warning") if not value contains "OK"
column amount:
style("success") if not value < 0
Case Sensitivity
String comparisons are case-insensitive by default. Use the (case) modifier for case-sensitive matching:
column code:
style("error") if value == "Error" (case)
style("warning") if value contains "WARN" (case)
column status:
# This matches "approved", "APPROVED", "Approved"
style("success") if value == "approved"
# This matches only "APPROVED"
style("info") if value == "APPROVED" (case)
Complete Examples
Example 1: Highlight Negative Values
Simple financial data with negative values highlighted:
column amount:
style("error") if value < 0
format("EUR")
Result:
- Negative values: red background, formatted as Euro
- Positive values: normal display, formatted as Euro
Example 2: Status Indicators with Color Coding
Map status codes to colors and labels:
column status:
format.enum(
source={
"draft": "Draft",
"pending": "Pending Review",
"approved": "Approved",
"rejected": "Rejected"
},
default="Unknown"
)
style("neutral") if value == "draft"
style("warning") if value == "pending"
style("success") if value == "approved"
style("error") if value == "rejected"
Result:
- "draft" → "Draft" with neutral background
- "pending" → "Pending Review" with yellow background
- "approved" → "Approved" with green background
- "rejected" → "Rejected" with red background
Example 3: Budget vs Actual with Thresholds
Compare actual spending against budget with warning thresholds:
column actual:
format("EUR")
style("success") if value <= col.budget * 0.8
style("warning") if value > col.budget * 0.8
style("error") if value > col.budget
column budget:
format("EUR")
Result:
- Actual ≤ 80% of budget: green background
- Actual > 80% but ≤ 100%: yellow background
- Actual > 100%: red background
Example 4: Financial Report with Multiple Rules
Complete financial report with headers, formatting, and conditional highlighting:
# Global styling for all tables
tables:
style(font_size="14px")
# Header row
row 0:
style("neutral", bold=True)
# Amount column
column amount:
format.number(precision=2, suffix=" €", thousands_sep=" ")
style("error") if value < 0
style("success") if value > col.target
# Percentage column
column progress:
format("percentage")
style("error") if value < 0.5
style("warning") if value between 0.5 and 0.8
style("success") if value > 0.8
# Status column
column status:
format.enum(
source={
"draft": "Draft",
"review": "In Review",
"approved": "Approved",
"rejected": "Rejected"
}
)
style("neutral") if value == "draft"
style("info") if value == "review"
style("success") if value == "approved"
style("error") if value == "rejected"
# Date column
column created_at:
format.date(format="%d %b %Y")
# Highlight specific important cell
cell (amount, 10):
style("accent", bold=True)
Result: A fully formatted financial report with:
- Bold headers with neutral background
- Euro amounts with conditional coloring
- Progress percentages with traffic light colors
- Status labels with appropriate colors
- Formatted dates
- Highlighted total row
Using the DSL Editor
Editor Features
The DSL editor provides a comfortable writing experience with:
Syntax highlighting:
- Keywords (column, row, if, not) are highlighted
- Functions (style, format) are colored differently
- Strings, numbers, and operators have distinct colors
Line numbers:
- Easy reference for error messages
- Quick navigation in large documents
Auto-indentation:
- Automatic indentation after scope declarations
- Tab key for manual indentation
- Maintains Python-style indentation
Autocompletion
The editor provides context-aware suggestions to help you write rules quickly and correctly.
How to trigger:
- Ctrl+Space - Manual trigger at any time
- Automatic - Triggers after typing
.,(,", or space in certain contexts
What can be autocompleted:
| Context | Suggestions |
|---|---|
| Start of line | column, row, cell, table, tables |
After column |
Column names from your DataGrid |
After row |
Row indices (0, 1, 2, ...) |
After table |
Table name from current DataGrid |
| Indented line | style(, format(, format. |
Inside style(" |
Style presets (primary, error, success, ...) |
After style( |
Preset names and parameters (bold=, color=, ...) |
Inside format(" |
Format presets (EUR, USD, percentage, ...) |
After format. |
Format types (number, date, boolean, text, enum, constant) |
After if |
value, col., row., not |
| After operand | Operators (==, <, >, contains, in, ...) |
After col. |
Column names |
| After operator | col., literal values, True, False |
Example workflow:
User types │ Suggestions
───────────────┼────────────────────────────────────
col │ column
column │ [column names from grid]
column amount: │ (new line, indent)
st │ style
style( │ "error", "warning", "success", ...
style("e │ "error"
style("error", │ bold=, italic=, color=, ...
style("error", bold=│ True, False
style("error") │ format(, format., if
style("error") if │ value, col., not
style("error") if value │ ==, !=, <, >, contains, in, ...
style("error") if value < │ [number input]
Syntax Validation
The editor provides real-time syntax checking as you type.
Error indicators:
┌─────────────────────────────────────────────────────┐
│ 1 column amount: │
│ 2 style("error" if value < 0 │
│ ▲▲▲▲▲▲▲▲▲▲▲▲▲ │
│ ╰─ Missing closing parenthesis │
│ 3 │
└─────────────────────────────────────────────────────┘
Visual feedback:
- Red underline - Syntax error at that position
- Gutter marker - Error icon in the line number area
- Tooltip - Hover over the error for details
Common errors and fixes:
| Error | Cause | Fix |
|---|---|---|
Expected ':' |
Missing colon after scope | Add : after scope name |
Expected indentation |
Rule not indented | Indent rule under scope |
Unexpected token |
Typo or invalid syntax | Check spelling, operators |
Missing closing quote |
Unclosed string | Add closing " or ' |
Missing closing parenthesis |
Unclosed function call | Add closing ) |
Unknown column |
Column doesn't exist | Check column name spelling |
Example - Before and after fixing:
Before (error):
column amount
style("error") if value < 0
Error: Expected ':' after column name
After (fixed):
column amount:
style("error") if value < 0
Managing Presets
Using Built-in Presets
Style presets (DaisyUI 5):
| Preset | Background | Text | Typical Use |
|---|---|---|---|
primary |
Primary theme color | Primary content | Main highlights, important data |
secondary |
Secondary theme color | Secondary content | Secondary highlights |
accent |
Accent theme color | Accent content | Accent highlights, special items |
neutral |
Neutral theme color | Neutral content | Headers, totals, summaries |
info |
Info (blue) | Info content | Information, notes |
success |
Success (green) | Success content | Positive values, completed items |
warning |
Warning (yellow) | Warning content | Warnings, thresholds exceeded |
error |
Error (red) | Error content | Negative values, errors, failures |
Formatter presets:
| Preset | Type | Configuration | Example Output |
|---|---|---|---|
EUR |
number | suffix: " €", thousands_sep: " ", decimal_sep: ",", precision: 2 | 1 234,56 € |
USD |
number | prefix: "$", thousands_sep: ",", decimal_sep: ".", precision: 2 | $1,234.56 |
percentage |
number | suffix: "%", precision: 1, multiplier: 100 | 45.2% |
short_date |
date | format: "%d/%m/%Y" | 29/01/2026 |
iso_date |
date | format: "%Y-%m-%d" | 2026-01-29 |
yes_no |
boolean | true_value: "Yes", false_value: "No" | Yes |
Creating Custom Presets
You can add your own presets to use across all DataGrids.
Adding a custom style preset:
from myfasthtml.controls.DataGridsManager import DataGridsManager
# Get the global manager
manager = DataGridsManager.get_instance()
# Add custom style preset
manager.add_style_preset("highlight", {
"background_color": "yellow",
"color": "black",
"font_weight": "bold"
})
# Use in DSL
column important:
style("highlight")
Adding a custom formatter preset:
# Swiss Franc currency
manager.add_formatter_preset("CHF", {
"type": "number",
"prefix": "CHF ",
"thousands_sep": "'",
"decimal_sep": ".",
"precision": 2
})
# Use in DSL
column price:
format("CHF")
Adding multiple presets:
# Custom style presets
manager.add_style_preset("urgent", {
"background_color": "#ff6b6b",
"color": "white",
"font_weight": "bold"
})
manager.add_style_preset("completed", {
"background_color": "#51cf66",
"color": "white",
"text_decoration": "line-through"
})
# Custom formatter presets
manager.add_formatter_preset("GBP", {
"type": "number",
"prefix": "£",
"thousands_sep": ",",
"precision": 2
})
manager.add_formatter_preset("compact_date", {
"type": "date",
"format": "%d/%m/%y"
})
Removing presets:
# Remove style preset
manager.remove_style_preset("highlight")
# Remove formatter preset
manager.remove_formatter_preset("CHF")
Reference
Style Properties
Complete reference of all style properties:
| Property | Type | Values | Description |
|---|---|---|---|
preset |
string | See Style Presets below | Preset name (applied first) |
background_color |
string | Hex, CSS name, or variable | Background color |
color |
string | Hex, CSS name, or variable | Text color |
bold |
boolean | True, False |
Bold text |
italic |
boolean | True, False |
Italic text |
underline |
boolean | True, False |
Underlined text |
strikethrough |
boolean | True, False |
Strikethrough text |
font_size |
string | CSS size value | Font size (e.g., "12px", "0.9em") |
Color values:
# Hex colors
style(color="#cc0000")
# CSS color names
style(color="red")
# DaisyUI CSS variables
style(color="var(--color-primary)")
style(background_color="var(--color-base-200)")
Combining properties:
# Preset + overrides
style("error", bold=True, font_size="16px")
# Multiple properties
style(background_color="#fffacd", color="#856404", bold=True, italic=True)
Style Presets
DaisyUI 5 color presets:
| Preset | Background CSS Variable | Text CSS Variable |
|---|---|---|
primary |
var(--color-primary) |
var(--color-primary-content) |
secondary |
var(--color-secondary) |
var(--color-secondary-content) |
accent |
var(--color-accent) |
var(--color-accent-content) |
neutral |
var(--color-neutral) |
var(--color-neutral-content) |
info |
var(--color-info) |
var(--color-info-content) |
success |
var(--color-success) |
var(--color-success-content) |
warning |
var(--color-warning) |
var(--color-warning-content) |
error |
var(--color-error) |
var(--color-error-content) |
Note: All presets use font_weight: "normal", font_style: "normal", text_decoration: "none" by default.
Formatter Types
Number Formatter
| Parameter | Type | Default | Description |
|---|---|---|---|
prefix |
string | "" |
Text before value |
suffix |
string | "" |
Text after value |
thousands_sep |
string | "" |
Thousands separator |
decimal_sep |
string | "." |
Decimal separator |
precision |
int | 0 |
Decimal places |
multiplier |
number | 1 |
Multiply before display |
Date Formatter
| Parameter | Type | Default | Description |
|---|---|---|---|
format |
string | "%Y-%m-%d" |
strftime pattern |
Boolean Formatter
| Parameter | Type | Default | Description |
|---|---|---|---|
true_value |
string | "true" |
Display for true/1 |
false_value |
string | "false" |
Display for false/0 |
null_value |
string | "" |
Display for null/None |
Text Formatter
| Parameter | Type | Default | Description |
|---|---|---|---|
transform |
string | - | "uppercase", "lowercase", "capitalize" |
max_length |
int | - | Truncate if exceeded |
ellipsis |
string | "..." |
Suffix when truncated |
Enum Formatter
| Parameter | Type | Default | Description |
|---|---|---|---|
source |
object | - | Mapping or datagrid reference |
default |
string | "" |
Label for unknown values |
Constant Formatter
| Parameter | Type | Default | Description |
|---|---|---|---|
value |
string | - | The constant text to display |
Formatter Presets
| Preset | Type | Configuration |
|---|---|---|
EUR |
number | suffix: " €", thousands_sep: " ", decimal_sep: ",", precision: 2 |
USD |
number | prefix: "$", thousands_sep: ",", decimal_sep: ".", precision: 2 |
percentage |
number | suffix: "%", precision: 1, multiplier: 100 |
short_date |
date | format: "%d/%m/%Y" |
iso_date |
date | format: "%Y-%m-%d" |
yes_no |
boolean | true_value: "Yes", false_value: "No" |
Operators Reference
Comparison Operators
| Operator | Description | Value Type | Example |
|---|---|---|---|
== |
Equal | Any | value == 0 |
!= |
Not equal | Any | value != "" |
< |
Less than | Number, Date | value < 0 |
<= |
Less or equal | Number, Date | value <= 100 |
> |
Greater than | Number, Date | value > 1000 |
>= |
Greater or equal | Number, Date | value >= 0 |
String Operators
| Operator | Description | Value Type | Example |
|---|---|---|---|
contains |
String contains | String | value contains "error" |
startswith |
String starts with | String | value startswith "ERR" |
endswith |
String ends with | String | value endswith ".pdf" |
Note: String operators are case-insensitive by default. Use (case) modifier for case-sensitive matching.
List Operators
| Operator | Description | Value Type | Example |
|---|---|---|---|
in |
Value in list | List | value in ["A", "B", "C"] |
between |
Value in range | List [min, max] | value between 0 and 100 |
Unary Operators
| Operator | Description | Example |
|---|---|---|
isempty |
Is null or empty string | value isempty |
isnotempty |
Is not null or empty | value isnotempty |
isnan |
Is NaN (Not a Number) | value isnan |
DSL Grammar (EBNF)
Formal syntax reference for the DSL:
// Top-level structure
program : scope+
// Scopes
scope : scope_header NEWLINE INDENT rule+ DEDENT
scope_header : column_scope | row_scope | cell_scope | table_scope | tables_scope
column_scope : "column" column_name ":"
row_scope : "row" INTEGER ":"
cell_scope : "cell" cell_ref ":"
table_scope : "table" QUOTED_STRING ":"
tables_scope : "tables" ":"
column_name : NAME | QUOTED_STRING
cell_ref : "(" column_name "," INTEGER ")" | CELL_ID
// Rules
rule : (style_expr format_expr? | format_expr style_expr?) condition? NEWLINE
condition : "if" comparison
// Comparisons
comparison : "not"? (binary_comp | unary_comp) case_modifier?
binary_comp : operand operator operand
| operand "in" list
| operand "between" operand "and" operand
unary_comp : operand ("isempty" | "isnotempty" | "isnan")
case_modifier : "(" "case" ")"
// Operators
operator : "==" | "!=" | "<" | "<=" | ">" | ">="
| "contains" | "startswith" | "endswith"
// Operands
operand : value_ref | column_ref | row_ref | cell_ref_expr | literal | arithmetic
value_ref : "value"
column_ref : "col." (NAME | QUOTED_STRING)
row_ref : "row." INTEGER
cell_ref_expr : "cell." NAME "-" INTEGER
literal : STRING | NUMBER | BOOLEAN
arithmetic : operand ("*" | "/" | "+" | "-") operand
list : "[" (literal ("," literal)*)? "]"
// Style expression
style_expr : "style" "(" style_args ")"
style_args : (QUOTED_STRING ("," style_kwargs)?) | style_kwargs
style_kwargs : style_kwarg ("," style_kwarg)*
style_kwarg : NAME "=" (QUOTED_STRING | BOOLEAN | NUMBER)
// Format expression
format_expr : format_preset | format_typed
format_preset : "format" "(" QUOTED_STRING ("," format_kwargs)? ")"
format_typed : "format" "." FORMAT_TYPE "(" format_kwargs? ")"
format_kwargs : format_kwarg ("," format_kwarg)*
format_kwarg : NAME "=" (QUOTED_STRING | BOOLEAN | NUMBER | dict)
dict : "{" (dict_entry ("," dict_entry)*)? "}"
dict_entry : QUOTED_STRING ":" QUOTED_STRING
// Tokens
FORMAT_TYPE : "number" | "date" | "boolean" | "text" | "enum" | "constant"
NAME : /[a-zA-Z_][a-zA-Z0-9_]*/
QUOTED_STRING : /"[^"]*"/ | /'[^']*'/
INTEGER : /[0-9]+/
NUMBER : /[0-9]+(\.[0-9]+)?/
BOOLEAN : "True" | "False" | "true" | "false"
CELL_ID : /tcell_[a-zA-Z0-9_-]+/
NEWLINE : /\n/
COMMENT : /#.*/
End of User Guide
For technical details about the implementation, see the developer documentation.