Two optional scripts, validate.js and process.js, cover anything a form's
declarative validation rules or a block's inline template can't - both plain
JavaScript via flutter_js, edited via the Script
Editor. Neither is required - a project with no
cross-field checks and no conditional layout content doesn't need either file.
- validate.js - cross-field validation.
- process.js - layout assembly and computed presentation data.
- Debugging - the two most common "it just doesn't work" reports.
The processing pipeline
Hitting Generate on Fill Out a Form runs, in this exact order:
- Static validation - the form's own
required/min/max/regexrules (see the Form Editor). Stops here if anything fails. validate.js- cross-field validation. Stops here if it writes anyerrors.process.js- layout assembly: decides which layout partials to include, and can prepare presentation data for blocks to use.- Render - the assembled layout is drawn onto the page canvas and saved to the
project's
output/folder.
Nothing about a submission is saved anywhere except the generated PDF itself - see Document Project Structure.
Conditions & Expressions
A block's condition property and a form's computed-field expression (see Form
Editor) both use a different,
simpler engine than validate.js/process.js/block templates - arithmetic and
field access only, not full JavaScript:
is_certified == true
sale_price > 0
trim_level == 'Sport' || trim_level == 'Premium'
inputs['sale_price'] * 1.08
Bare field names and inputs['field_id'] bracket access both work and mean the same
thing. Falsy (false, 0, "", null) hides the block or fails the condition;
leaving condition off entirely always shows the block.
There's no js:-prefixed escape hatch for a condition - if you need something more
complex than this syntax allows, that belongs in validate.js (rejecting the
submission) or a {...} block template segment (formatting for display), not in
condition.
Where each engine applies
It's easy to mix these up since they all look like "put a formula here" - here's the actual split:
| Where | Engine | What it can do |
|---|---|---|
validate.js, process.js |
Real JavaScript (flutter_js) |
Anything - loops, method calls, string building |
A block's text/data inside {...} (or a grid's data, unwrapped) |
Real JavaScript (flutter_js) |
Same as above, evaluated fresh per block at render time |
A block's condition |
The expressions package |
Arithmetic, comparisons, field access only - no method calls |
A computed field's expression in form.json |
The expressions package |
Same restricted syntax as condition |