Calculated Fields and JavaScript in Forms¶
Rules¶
- All formulas must be a single-line expression — no multi-line code or variable declarations.
- If writing complex logic: write it multi-line first (in a text editor or GPT), then collapse to one line.
- Use
+for string concatenation — but be careful with integers and dates (see below). - Use
||for OR,&&for AND. - Use
?/:shorthand for conditionals. - Always bracket complex logic with
().
Field Types: Text vs Numeric¶
Understanding field type behaviour is critical — many bugs come from mixing types.
Text Fields (String)¶
- Designed to hold string data. Numeric data can be stored in a text field, but this changes the field's behaviour.
- Addition (
+) on a text field behaves as concatenation, not arithmetic. - The SUM calculation across group elements does not handle string fields — it will not concatenate and will not aggregate numerically.
- At the time of writing, there is no reliable, scalable way to concatenate text across group elements in Versaa.
- Text fields are incompatible with numeric field types — explicit type conversion is needed to get numeric behaviour from a text field. This can be done inside a calculation by explicitly assigning to a numeric data type.
Numeric Fields (INT)¶
- Numeric fields (e.g.
INT) support mathematical operations: aggregation (SUM) and subtraction work correctly. - JavaScript in calculations can treat a numeric field as either text or a number — be explicit about which behaviour you need.
- Only numbers are acceptable in an INT field — inserting non-numeric data will cause errors.
- Numeric precision may be lost on an INT field — avoid using INT for values that need decimal precision.
Basic Patterns¶
String concatenation:
Conditional (inline if):
Combining conditions:
Integer / Date Fields¶
Integer fields and text fields look identical in the Aareon Mobile app but behave differently in the database. This causes hard-to-diagnose bugs.
- Never concatenate integers or date/time fields directly with text. Create a text field copy (e.g.,
z_InstanceNameA) first. - During development: add a type label to field captions (
Age [int]vsAge [str]) to tell them apart at a glance. Remove before deploying to Live.
// Wrong — may cause bugs
$formItem.integerField + " items"
// Right — convert first
$formItem.integerField.toString() + " items"
Formatting a Date Field as a String¶
Date/DateTime FormItems (type="Date" or type="DateTime") expose a JavaScript Date object at formula evaluation time. You cannot use String(dateField) or .toString() — these produce values like "Mon Dec 14 2037 00:00:00 GMT+0100 (BST)", and .split(" ")[0] gives the day-of-week ("Mon"), not the date.
Also do NOT use GetSelectedItemValue on a date column — it returns the same JS Date object.
Correct pattern — use Date methods on $formItem¶
// Produces "14/12/2007" (D/M/YYYY, no zero-padding)
$formItem.InstallDate
? $formItem.InstallDate.getDate() + "/" + ($formItem.InstallDate.getMonth()+1) + "/" + $formItem.InstallDate.getFullYear()
: ""
Collapsed to one line (required by Versaa):
$formItem.InstallDate?$formItem.InstallDate.getDate()+"/"+($formItem.InstallDate.getMonth()+1)+"/"+$formItem.InstallDate.getFullYear():""
Note:
.getMonth()is zero-based — January = 0, so always add 1.
Use a z_ String helper field for document templates¶
The Word Connector renderer reads from the saved task XML, not from live formula evaluation. To get a formatted date into a PDF document:
- Add a
z_FieldName_FmtString FormItem with the formula above - Set
archivable=True(so the value is saved to task XML) - Set
availableForDocumentRendering=True(so it appears as valid in the template) - Bind the template placeholder to
z_FieldName_Fmt, not the original date field
See forms/word-connector-templates.md for full detail.
Formula Expression length limit (~178 chars)¶
The Expression text of a formula is stored in a SQL column with a maximum length of approximately 178 characters. Exceeding this causes import error:
8152: String or binary data would be truncated
Keep date formatting expressions as short as possible. The pattern above is ~133–151 chars depending on field name length — safely within the limit.
Date of Birth → Age Calculation¶
new Date().getFullYear() - new Date(QL_DateOfBirth_1).getFullYear() - (new Date() < new Date(new Date().getFullYear(), new Date(QL_DateOfBirth_1).getMonth(), new Date(QL_DateOfBirth_1).getDate()) ? 1 : 0)
Replace QL_DateOfBirth_1 with your actual DOB field name. Accounts for whether the birthday has occurred yet this year.
String Formula Type (Email, Document Names, Subjects)¶
Several platform form items use Formula → Calculations → String type, not JavaScript. Syntax differs:
- Literal text in double speech marks:
"some text" - Form item values referenced by name (use the value picker:
V= value,N= name) - Use
+to concatenate - Always add spaces inside speech marks at text boundaries — otherwise words run together
Document name (unique per submission):
Email subject:
Email body:
"Attached is the " + [V.component] + " component replacement request for property reference " + [V.QL_PropertyID] + " on " + [QL_StartForm].toString("DD")
Email attachment filename:
.toString("DD") for dates — when concatenating a date form item into a string, append .toString("DD") to control format. Without it, the raw value may not concatenate cleanly.
Tip: Open an existing form that already sends email documents (e.g., Written Scheme Review, Building Safety Check) and copy the expression — adapt text/field references for your form.