FSM Expressions and Template Tags
Use expressions and template tags to provide configuration values that depend on other data. FSM Mobile expressions can calculate element values and change element behavior during form completion. Template tags can insert data into a resource definition before FSM Mobile renders it.
This topic covers:
Choosing a Value Method
Choose a method based on when the value is determined and whether it must respond to changes in FSM Mobile. The following table compares the available methods.
|
Method |
Purpose |
Example |
When the Value Is Determined |
|---|---|---|---|
|
Static value |
Supplies a fixed configuration value. |
|
When the configuration is used. |
|
FSM Mobile expression |
Calculates an element property from element data. |
|
When the element is initialized, subject to the saved-value rules, and when a referenced local element property changes. |
|
Template tag |
Supplies a value from the context available when a resource definition is prepared. |
|
When the resource definition is prepared. It does not create a local listener for subsequent changes to an FSM Mobile element. |
For the properties and accepted values of each element type, see FSM Mobile Element (Block) Reference. For the properties of a resource definition, see FSM Mobile Resource Properties Reference.
Defining Mobile Expressions
An FSM Mobile expression is a JavaScript expression written as a JSON string in an element property. It must return a value accepted by that property and element type.
For example, the following element-definition fragment makes a signature visible and required when you check the Completed box:
{
"completed": {
"type": "checkbox",
"label": "Completed",
"value": false
},
"approvalSignature": {
"type": "signature",
"label": "Approval Signature",
"hidden": "!completed.value",
"required": "completed.value"
}
}
Place an element-definition fragment within the element object of the appropriate routes/mobile resource. The property names in the fragment identify the elements.
Expression Rules
When writing an expression:
-
Use one expression that produces a value. Do not begin it with
returnor use a sequence of statements. -
Refer to an available element property with dot notation, such as
quantity.valueorthis.value. -
Include a recognized element-property reference. A string containing only a calculation or a function call does not, by itself, establish an FSM Mobile expression binding.
-
Keep structural properties, including an element's type, name, parent, URI, and column definition, fixed. Use expressions only for properties that support expressions.
-
Return the correct value type. A string such as
"false"is not the Boolean valuefalse. -
Handle empty values explicitly. Avoid results such as
undefined,NaN, or infinity. -
Avoid circular dependencies, such as two calculated elements whose values depend on each other.
-
Keep calculations free of record writes, network calls, and other side effects. An expression can run repeatedly during work on a form.
When creating element names for expressions, start with a letter or an underscore, followed by letters, digits, or underscores. Avoid spaces, punctuation, and JavaScript reserved words. Use names consistently, including letter case.
Use dot notation for the element-property reference even if the rest of the expression uses array access or other JavaScript syntax. For example, readings.value[0] identifies readings.value as the input. The reference readings['value'] does not provide the same recognized reference.
Returning Accepted Values
The expression result must match the accepted static value for the property. The following table illustrates common cases. It does not replace the property reference.
|
Property or Use |
Required Result |
Example |
|---|---|---|
|
|
Boolean |
|
|
A label or a Text value |
String |
|
|
A Number value |
Number, or an empty value accepted by the element |
|
|
Select |
Array of option objects |
|
|
Single-select |
One selection object, or |
|
|
Multiple-select |
Array of selection objects, or an empty array |
|
|
A Date, Time, or Date-Time value |
A string in the required format, or an empty string |
|
The Select examples assume that the referenced options exist and contain the required option properties. Do not reference this.options[0] unless the options array has an entry.
For the effect of changing a Select's options on its current selection, see Select Defaults and Stored Values.
Changing Select multiple does not provide a general conversion between a single selection object and an array of selections. Supply a compatible value when changing selection mode.
For example, the following fragment switches between single-selection and multiple-selection modes when Allow Several changes. Its value expression returns null when the Allow Several box is cleared and an empty array ([]) when the box is checked. These represent no selection in the respective modes, so switching modes clears any existing selection:
{
"allowSeveral": {
"type": "checkbox",
"label": "Allow Several",
"value": false
},
"chosenServices": {
"type": "select",
"label": "Services",
"autoselect": false,
"multiple": "allowSeveral.value",
"value": "allowSeveral.value ? [] : null",
"options": [
{ "id": "inspection", "label": "Inspection" },
{ "id": "repair", "label": "Repair" }
]
}
}
Changing the selection mode in this example clears the current selection. If selections must be retained, define the required conversion.
Expression Evaluation and Saved Values
Expressions depend on referenced element properties. When a referenced local property changes, FSM Mobile evaluates the expression again and applies its result to the target property.
For example, this fragment calculates a line total when Quantity or Unit Price changes:
{
"quantity": {
"type": "number",
"label": "Quantity",
"min": 0,
"value": 1
},
"unitPrice": {
"type": "number",
"label": "Unit Price",
"min": 0,
"value": 0
},
"lineTotal": {
"type": "number",
"label": "Line Total",
"readonly": true,
"value": "quantity.value === null || unitPrice.value === null ? null : Math.round(quantity.value * unitPrice.value * 100) / 100"
}
}
During initialization, FSM Mobile handles value expressions differently from expressions on other properties:
-
If an element has no supplied record value, its
valueexpression can provide the initial value. -
If an element already has a supplied record value, FSM Mobile preserves that value when opening the record. It does not automatically replace it with a fresh calculation.
-
A subsequent change to a referenced local property can recalculate the value and replace the preserved value.
-
Expressions on other properties, such as
hiddenandrequired, are evaluated during initialization.
Setting readonly to true prevents the user from editing the element directly. It does not force a stored value to be recalculated when an existing record opens.
If a calculated value is overridden, changing a referenced local property can replace that override.
Referencing Element Data
An element property can refer to another available element's properties or to properties of the current element.
|
Reference |
Meaning |
Example |
|---|---|---|
|
|
A property of an available element. |
|
|
|
A property of the element containing the expression. |
|
|
A shared element URI followed by a property |
Data from an element registered for sharing. |
|
Use this to refer to another property of the current element. For example, avoid referencing this.value in a value expression because that property would depend on itself.
Table Elements
Within a table row, child-element references use the values from that row. A quantity column and a price column can therefore calculate a total column independently for each row.
A top-level expression can use a table's value, which is an array of row data. Check for an empty array before accessing a row, and use the actual child-element names when reading row values.
Do not assume that a child element can directly refer to an unrelated child in another row or to every element outside its table. Use references within the same row or an explicitly shared element. Confirm other cross-scope arrangements against the FSM Mobile version used by the account.
Sharing Data Between Resources
Use a shared element's registered uri followed by the required property. For example, services.options reads the option list registered under the URI services. It uses the URI, which can differ from the element's name or the supplying resource's ID.
The supplier must be loaded before the reference can be used. For complete supplier and consuming Select examples and resource-loading rules, see Sharing Data Between Resources. Avoid URI names that conflict with unrelated local element names.
Shared data must be available when the consuming expression runs. Do not assume that updating a different resource will immediately recalculate an already open form. After refreshing the supplying data, reopen the consuming resource to use it.
Reusing Calculations
Custom element properties can hold intermediate values for use by other expressions. These properties contain calculation data rather than additional standard element controls and are not automatically NetSuite fields.
The following fragment uses an intermediate Boolean property to calculate a result label:
{
"reading": {
"type": "number",
"label": "Reading",
"value": null,
"limit": 100,
"overLimit": "this.value !== null && this.value > this.limit"
},
"readingResult": {
"type": "text",
"label": "Result",
"readonly": true,
"value": "reading.value === null ? '' : (reading.overLimit ? 'Over limit' : 'Within limit')"
}
}
Avoid names that conflict with standard element properties. For larger calculations used by several forms, an imported JavaScript function can provide one implementation. See Importing JavaScript, JSON, and CSS Files.
Removing Duplicate Array Values
The unique(array) helper returns an array containing the first occurrence of each distinct value. An optional second argument identifies a property to compare when the entries are objects, for example unique(this.options, 'id') in a separate custom property. Without that argument, object entries are compared by identity rather than by matching all their contents.
The expression must still contain an available element-property reference, and the result must be accepted by the target property.
Using Template Tags
A template tag uses ${ expression } syntax inside a configuration string. It evaluates against the data available when the resource definition is prepared.
Template tags can be used in resource configuration values, including nested article, element, and form values. Their result must be accepted by the target property. Template processing does not remove the property's type or value requirements.
A tag ends at a closing }. Nested JavaScript braces are not supported within the tag. Avoid inline object literals or function bodies that contain braces. To return an object or array, reference existing data in the available context or resource-local data, such as ${ choiceData }. The target property must still accept that result.
Template Context
The following table describes the context available to template tags.
|
Context |
Purpose |
Example |
|---|---|---|
|
|
Data supplied for the current job or event. Additional properties depend on its mapping. |
|
|
|
Data supplied for the FSM Mobile user. Additional properties depend on its mapping. |
|
|
|
Resource-selection and request values supplied for this resource. Available properties depend on the request. |
|
|
Resource-local data |
Additional named data defined in the resource for use by its template tags. |
|
The options.search example applies when a request supplies a search value. It is not a value guaranteed for every resource request.
Use the names defined by the event or user mapping. A template tag does not make an unmapped NetSuite field available. Mapping is covered in FSM Searches and Field Mapping.
Whole Tags and Text Interpolation
When a string consists of one complete template tag, the result retains the type produced by the expression. When a tag is included within other text, its result becomes part of a string.
|
Configuration Value |
Result |
Result Type |
|---|---|---|
|
|
|
Number |
|
|
|
String |
|
|
|
Boolean |
|
|
|
String |
For example, use a whole tag when a Boolean result is required. Adding a text prefix would produce a string instead.
Handle missing context values explicitly. For a text value that should be blank when no mapped date is available, use ${ event.date || '' }. Do not rely on an unavailable property automatically becoming an empty string.
Resource-Local Template Data
Additional top-level properties in a resource definition can provide data for that resource's template tags. Template processing uses these properties but does not return the properties as additional FSM Mobile resource properties.
For example, the following resource-definition fragment uses one local label in a Heading element:
{
"headingLabel": "Inspection",
"element": {
"inspectionHeading": {
"type": "heading",
"label": "${ headingLabel }"
}
}
}
Keep resource-local template data distinct from custom element properties. Template processing uses resource-local data to prepare the resource. FSM Mobile expressions can use custom element properties. Avoid local data names that conflict with the template context.
Combining Template Tags and Mobile Expressions
A template tag can supply a constant within an expression that will subsequently run in FSM Mobile. For example, the following property uses a numeric event.limit supplied by the event mapping:
{
"hidden": "reading.value > ${ event.limit }"
}
Template processing first substitutes the mapped limit. FSM Mobile then binds the resulting expression to reading.value.
Ensure that the substituted value produces valid JavaScript and has the intended type. Do not insert unescaped free-text values into an expression. Prefer a separate configured property when the value requires quoting or a more complex representation.
Working with Dates and Times
The following table lists helpers for FSM Mobile expressions.
|
Helper |
Purpose |
Result |
|---|---|---|
|
|
Formats a date-like value. |
An object containing |
|
|
Gets the current date and time when the expression runs. |
An object containing |
These helpers are for FSM Mobile expressions. Do not assume that these helpers are available in server-side template tags.
Date and Time Result Formats
The following table lists the required formats for nonempty date and time values.
|
Element Type |
Required Nonempty Value |
Example |
|---|---|---|
|
Date |
|
|
|
Time |
|
|
|
Date-Time |
|
|
Use format(value).date, format(value).time, or format(value).datetime as appropriate. These helpers do not perform a business-specific time zone conversion. Account for the intended time zone when choosing the source value.
A blank input to format() is treated as the current date and time. Guard a blank source value if the result should remain blank.
For example:
{
"sourceDateTime": {
"type": "datetime",
"label": "Source Date-Time",
"value": ""
},
"derivedTime": {
"type": "time",
"label": "Derived Time",
"readonly": true,
"value": "sourceDateTime.value ? format(sourceDateTime.value).time : ''"
}
}
If format() cannot parse a date-like value, the helper can return empty strings. Invalid expression results are not guaranteed to be ignored or restored to a previous value. Check the result and the element's validation requirements.
Using the Current Time
Include a recognized input that determines when the current-time expression should run. The following fragment sets the time when the Use Current Time box is checked and clears the time when the box is cleared:
{
"useCurrentTime": {
"type": "checkbox",
"label": "Use Current Time",
"value": false
},
"capturedTime": {
"type": "time",
"label": "Captured Time",
"step": 60,
"value": "useCurrentTime.value ? now().time.replace(/:\\d\\d$/, ':00') : ''"
}
}
The helper now().time includes seconds. In this example, the replacement sets the seconds to 00 for a minute-aligned result. It does not round to the next minute. Use this approach when the configured time entry and its destination require minute-aligned values.
now() samples the time when the expression runs. It does not continuously update the element over time. A bare string such as "now().time" also lacks the element-property reference needed to establish the binding.
For element limits, defaults, and time-step behavior, see FSM Mobile Element (Block) Reference.
Importing JavaScript, JSON, and CSS Files
Use routes/mobile.import to load files that support FSM Mobile customization. JavaScript files can provide reusable functions, JSON files can provide reusable data, and CSS files can provide styles.
|
File Type |
Use in FSM Mobile |
|---|---|
|
JavaScript ( |
Loads script code. Functions intended for expression use must be accessible in the FSM Mobile page. |
|
JSON ( |
Provides a global variable whose name is the import ID and whose value is the parsed JSON. |
|
CSS ( |
Loads a stylesheet. It does not provide an expression value. |
Configuring Imports
Configuring Imports
-
Store the required files in the NetSuite File Cabinet.
-
Add an
importobject underroutes/mobilein the custom configuration. -
For each entry, use a unique import ID as the property name and the File Cabinet path as its value.
-
Save the configuration and refresh FSM Mobile to load the updated configuration and files.
For example:
The file paths in this example are placeholders. Replace each path with the path of an existing file in your NetSuite account.
{
"routes/mobile": {
"import": {
"fsmCalculations_v1": "/SuiteScripts/FieldService/fsm-calculations.js",
"fsmRates_v1": "/SuiteScripts/FieldService/fsm-rates.json",
"fsmStyle_v1": "/SuiteScripts/FieldService/fsm-style.css"
}
}
}
Use JSON import IDs that are valid JavaScript variable names.
Using an Imported Function
The JavaScript file can define a reusable function such as:
function fsmLineTotal(quantity, unitPrice) {
if (quantity === null || unitPrice === null) return null;
return Math.round(quantity * unitPrice * 100) / 100;
}
An element can call it in a value expression:
{
"value": "fsmLineTotal(quantity.value, unitPrice.value)"
}
The references to quantity.value and unitPrice.value establish the inputs. The import ID identifies the script to load. It does not automatically rename the function or add a prefix to its name.
Using Imported JSON Data
For example, fsm-rates.json can contain:
{
"standard": 125,
"premium": 175
}
With the import ID fsmRates_v1, an expression can use the data as follows:
{
"value": "hours.value === null ? null : hours.value * fsmRates_v1.standard"
}
This example depends on the local hours.value property. The imported data supplies a rate. It is not a changing FSM Mobile element input.
Updating Imported Files
FSM Mobile caches imported files for offline use after download. Changing a file's contents without changing its import ID can leave a device with a cached version.
Updating Imported Files
-
Update the file in the File Cabinet.
-
Change its import ID in the configuration, for example from
fsmCalculations_v1tofsmCalculations_v2. -
For a JSON import, update expressions that refer to the old ID because the ID is also the variable name.
-
For a JavaScript import, update function calls only if the file's public function names changed.
-
Save the configuration and refresh FSM Mobile with an active internet connection to download the changed files.
Do not assume that an offline device can obtain a newly configured file before reconnecting.
Expression Logging
Enabling Expression Logging
"routes/mobile".log controls expression messages in the browser console. The default value is false. Set log to true to turn on logging.
{
"routes/mobile": {
"log": true
}
}
The following table describes element-binding messages.
|
Message |
Meaning |
|---|---|
|
|
An expression and its dependencies are initialized. |
|
|
An evaluated result is assigned. |
|
|
The expression could not be parsed. |
|
|
The expression failed during evaluation. |
Other evaluation paths can report ExpressionError. Set log to false to turn off these messages. For log and request capture, see FSM Performance and Data Collection.
The following example shows the default log value:
{
"routes/mobile": {
"log": false
}
}
Related Topics
- FSM Configuration Reference
- FSM Mobile Element (Block) Reference
- FSM Searches and Field Mapping
- FSM Mobile Resource Properties Reference
- FSM Configuration
-
FSM Performance and Data Collection - performance measurement and collection of requests, responses, and relevant logs.