Reusable Logic in Mobile Form Expressions
Use the following approaches to organize and reuse logic in mobile form expressions:
-
Keep expressions short.
-
Store reusable intermediate results in custom properties.
-
Use imported pure functions for calculations that contain several operations.
Custom Properties for Reusable Mobile Form Expression Results
Elements can contain custom properties in addition to their standard properties. A custom property can contain a static value or an expression.
The following configuration calculates weight.pass and reuses it:
{
"weight": {
"label": "Weight",
"type": "number",
"target": 100,
"tolerance": 0.1,
"pass": "Math.abs(this.target - (this.value || 0)) < this.tolerance"
},
"fail1": {
"label": "Fail Reading 1",
"type": "number",
"hidden": "weight.pass"
},
"fail2": {
"label": "Fail Reading 2",
"type": "number",
"hidden": "weight.pass"
},
"fail3": {
"label": "Fail Reading 3",
"type": "number",
"hidden": "weight.pass"
}
}
A reusable custom property avoids repeating the tolerance calculation in each hidden property.
Imported Pure Functions in Mobile Form Expressions
A pure function returns the same result for the same input values and does not change form state or external data.
For logic that appears in multiple expressions, create a JavaScript function. Upload the file to the File Cabinet and register it with the FSM Configuration import option.
The following form expression calls a haversine function:
{
"latitude": {
"label": "Latitude",
"type": "number"
},
"longitude": {
"label": "Longitude",
"type": "number"
},
"distance": {
"label": "Distance",
"type": "number",
"readonly": true,
"originLatitude": -37.8541542,
"originLongitude": 145.1040064,
"value": "haversine(this.originLatitude, this.originLongitude, latitude.value, longitude.value)"
}
}
The imported file can define the calculation:
function isNumber(value) {
return !isNaN(parseFloat(value));
}
function toRadians(degrees) {
return degrees * Math.PI / 180;
}
function haversine(latitude1, longitude1, latitude2, longitude2) {
if (
isNumber(latitude1) &&
isNumber(longitude1) &&
isNumber(latitude2) &&
isNumber(longitude2)
) {
return (
6362.4098345775 *
(Math.acos(
Math.sin(toRadians(latitude1)) * Math.sin(toRadians(latitude2)) +
Math.cos(toRadians(latitude1)) *
Math.cos(toRadians(latitude2)) *
Math.cos(toRadians(longitude1 - longitude2))
) || 0)
);
}
return 0;
}
Register the JavaScript file with a unique import ID:
{
"import": {
"customfunctions_v1": "/SuiteScripts/FieldService/haversine.js"
}
}
The function must be available in the global scope of the imported script. Keep imported functions pure: pass all required values as parameters, return a value synchronously, and do not modify form state.
Imported Data Sets in Mobile Form Expressions
Static JSON data can also be used by an expression. Register the JSON file with the FSM Configuration import option. The import ID becomes the name of a global variable containing the parsed JSON data.
The following expression passes imported topography data to a pure function:
{
"elevation": {
"label": "Elevation",
"type": "number",
"readonly": true,
"originLatitude": -37.8541542,
"originLongitude": 145.1040064,
"value": "getElevation(topodata, this.originLatitude, this.originLongitude)"
}
}
The JavaScript file defines the function:
function getElevation(topography, latitude, longitude) {
// Return the elevation found in the supplied topography data.
}
Register both files:
{
"import": {
"topomath_v1": "/SuiteScripts/FieldService/utils/topography.js",
"topodata_v1": "/SuiteScripts/FieldService/regional-topography.json"
}
}
For import behavior, supported file types, and caching guidance, see Importing Files into the Mobile App.