Form Expressions Language
Form Expressions Language
MobileForce Expressions: Language and Usage in Low Code Application Development
The Visual software development constructs in MobileForce Low-code/No-code Platform empower the citizen developer to visually create and connect with drag and drop, application components to easily create powerful enterprise applications. However, there are often situations when someone with development skills (for example, a business analyst) that go beyond the citizen developer, would like to rapidly construct custom forms or UI elements using expressions to combine existing constructs in a powerful yet fairly composable manner. It is precisely for this purpose that MobileForce Expressions are created as a powerful enhancement to the MobileForce Low-code/No-code platform.
MobileForce expressions extend the automation capabilities of the MobileForce Platform in ways that otherwise could only be achieved by an enterprise software developer, but without the learning and implementation overhead of a software development environment.
The common expression language defined here is the common foundation, used to create powerful automation features in several different MobileForce products such as CPQ, Forms, and potentially even Field Service.
Simply put, MobileForce expressions enhance forms with dynamic functionality that enable dynamic (i.e., at run-time) changes to the value of form fields and sections, and in general any form elements. Furthermore, MobileForce expressions also support dynamic modification to the visibility and editability of form elements. MobileForce expressions are easy to write using plain text fields within various elements of MobileForce Applications such as CPQ, and potentially also Field Service. Within MobileForce CPQ, expressions are specifically used to enhance Rules, Triggers, Macros, Email Templates etc.
When used in CPQ rules, MobileForce expressions specify a trigger condition for a configuration, pricing, or approval rule. When the trigger condition evaluates to true, the action for that rule is executed. When used in macro variables, one can specify a MobileForce expression instead of a variable. Please note that MobileForce expressions are much more likely to be used in forms and CPQ rules, and rather lightly used in Macros.
In forms, MobileForce expressions are used for:
- Specifying the value of an input
- Specifying whether an input is read only or disabled.
- Specifying whether an input, section, table, row, column, or tab is hidden.
- Filtering picklist values.
In Quotes, MobileForce expressions are also used for:
- Triggers for configuration, pricing, or approval rules
- Reading email addresses from a form for an approval group.
- Macro variables in email templates or approver emails.
- Filtering document templates
- Control of Visibility of generated docs and doc templates
MobileForce expressions are almost invariably computed on the client side: the dynamic evaluation of expressions enables the Form elements within which MobileForce expressions are used to be highly responsive. Form expressions are evaluated locally in the form element to which they are tied, and make no changes to the surrounding context outside the form element. Hence their evaluation does not result in any side effects. MobileForce expressions include not only traditional values, identifiers, and variables combined using operators, but also include some pre-defined functions that enhance expressions.
MobileForce Expression Language (MFEL)
Often, expressions in MobileForce are used in forms, CPQ rules, triggers, macros, email templates, etc. All of these uses build upon MFEL in unique ways.
In order to define the MobileForce Expression Language, we start with primitives:
1. Primitive Values
The following primitive values are used in both Forms Formula and Expressions as well as CPQ Formula, Rules, Expressions, Functions and Variables. The only supported primitive values are strings, numbers, and JSON key/value objects. Numbers will be represented internally as double precision numbers. Strings will be automatically converted to numbers when necessary and vice versa. There is no boolean type. A value is considered to be false if it is the empty string, zero or the string "0". Otherwise, it is considered to be true.
A JSON key/value object is a string that follows the JSON object format. The JSON object must have a "key" and a "value" field. An example JSON key/value object is {"key": 1, "value": "One"}. The "key" field contains the actual or stored value while the "value" field contains the user-displayable string. JSON key/value objects are often used for picklist inputs. For example, a "user" picklist input may have its database ID stored in the "key" field and the user's name in the "value" field.
A JSON key/value value in any arithmetic or conditional expression will be automatically converted to its key. For example '{"key": 1, "value": "One"}' + 3 will be evaluated to 4.
2. Form Formula
Code snippet
formula = "=" expression
Augmented Backus-Naur Form
To allow the dynamic updating of certain fields based on the data provided by other fields, expressions can be used in some of the input attributes. These expressions will always start with a '=' character and are inspired-by/use a subset of MS Excel formula syntax. Only string and numeric scalar data types are supported together with a limited set of allowed functions. The input fields of formula can be referenced by their names. A formula can only reference input fields that have been specified previously the current input.
Formulae are allowed in the "value" attribute of inputs of type "readonly" and "hidden". Formulae can also occur in the "hidden" and "disabled" attributes for inputs.
Formulae can be used in FormSection attributes, specifically the hidden and lock attributes.
Formulae can also be used in a Row Element or Col Element which represent a row or a column of fields in a section. Specifically, the hidden attributes of these elements can include a formula.
Formula can also be used in the Input Attributes of an Input Element, specifically within the readonly type field, the hidden and value fields, disabled attribute, the invalidmessage attribute, the listitemfilter, the readonly and the validate attributes.
Now we can define Form expressions as follows:
2.1. Form Expressions
Form Expressions are specified using an augmented Backus Naur form metalanguage, often called ABNF
Note: You can now use
Code snippet
${expr}
Plain text
macros in any string literal in form expressions. So rather than typing
Code snippet
"id = '" & id & "'"
Plain text
you can now use
Code snippet
"id = '${id}'"
Plain text
instead.
2.2. Form Built-in Functions
The following built-in functions are supported in MobileForce expressions:
- ABS(number): Return the absolute value of the given number.
- AND(arg1, arg2, ...): Return the logical AND of the given arguments.
- IF(cond, then-expr, else-expr): If the first argument is true, return the second argument, else return the third argument.
- INT(number): Round the given number down to the nearest integer.
- MAX(num1, num2, ...): Return the maximum value of the given arguments.
- MIN(num1, num2, ...): Return the minimum value of the given arguments.
- NOT(expr): Return the logical NOT of the given argument.
- OR(arg1, arg2, ...): Return the logical OR of the given arguments.
- ROUND(number [, num-digits]): Round the given number to the nearest integer. If
num-digitsis specified, then the specified number of digits after the decimal point will be displayed. - SEARCH(needle, haystack [, offset]): Return the index of the needle string within the haystack string. If the needle is not in the haystack, return -1.
- REPLACE(str,strBy,InString): Replaces str by strBy in InString
- STRLEN(InString): Return the length of the "InString" string argument
- SUBSTRING(InString, pos, len): Returns the portion of the InString that starts at the position pos and is of length len. For boundary conditions, refer to the C++ substr function.
- COUNT(array): Returns the count of the number of elements in the given array.
- SUM(array [, fieldName]): Returns the sum of all the elements in the given array. If 'fieldName' is specified, then the array is assumed to be an array of objects instead of an array of numbers. 'fieldName` specifies which field in the array of objects should be summed together.
- AVG(array [, fieldName]): Returns the average of all the elements in the given array. If 'fieldName' is specified, then the array is assumed to be an array of objects instead of an array of numbers. 'fieldName` specifies which field in the array of objects should be averaged together.
- ARRAY_MIN(array [, fieldName]): Returns the minimum of all the elements in the given array. If 'fieldName' is specified, then the array is assumed to be an array of objects instead of an array of numbers. 'fieldName` specifies which field in the array of objects should be read.
- ARRAY_MAX(array [, fieldName]): Returns the maximum of all the elements in the given array. If 'fieldName' is specified, then the array is assumed to be an array of objects instead of an array of numbers. 'fieldName` specifies which field in the array of objects should be read.
- IN(element, array): Return true if the given element is in the given array. If the second argument is not an array, then return true if the two arguments are equal.
- ACLMATCH(acl [, array]): Return true if the given ACL matches the given array. The ACL uses MobileForce's ADL ACL syntax. The array must be an array of strings. If the second argument is missing, an array of the currently logged in user's roles is used.
- CURRENCY_FORMAT(number [, format [, locale]]): Format the given number as a currency, using PHP's money_format() function. The 'format' and 'locale' arguments are deprecated.
- NUMBER_FORMAT(number [, decimals [, decPoint [, thousandsSep]]]): Format the given number using PHP's number_format() function.
- DATE_FORMAT(date [, format [, timezone]]): Format the given date or date/time using the PHP's date() function.
- KEY(arg): If the given argument is a JSON key/value object, return the 'key' field of the object. Otherwise, return the argument unchanged.
- VALUE(arg): If the given argument is a JSON key/value object, return the 'value' field of the object. Otherwise, return the argument unchanged.
- KEYVALUE(key, value): return a JSON key/value object, whose key and value are the given arguments.
- DATEADD(date, val, unit): Adds the given value to the given date or date/time. 'date' must be a valid date or date/time string in ISO-8601 format. 'val' must be an integer. 'unit' identifies the unit-type of the value. 'unit' must be one of: 'y', 'm', 'd', 'w', 'h', 'i', or 's'. ('m' is months, 'i' is minutes).
- TODAY(): Return today's date.
- NOW(): Return todays's date and time.
- JOIN(separator, array): Returns a string that is a concatenation of the given array values separated by the given separator string. For example,
JOIN(',', ['A', 'B', 'C'])will return 'A,B,C'. If the second argument is not an array, this function will return it unchanged.
JOIN(separator, array[, nonempty]): Returns a string that is a concatenation of the given array values separated by the given separator string. For example, JOIN(',', ['A', 'B', 'C']) will return 'A,B,C'. If the second argument is not an array, this function will return it unchanged.
By default, empty elements will be shown between delimiters; unless you set third optional parameter to 1, in which case empty elements won't show.
- CASE(value, key1, expr1, key2, expr2, ...): This function acts similar to a switch statement in other languages, or to a nested sequence of IF() form expressions. (that is,
IF(value=key1, expr1, IF(value=key2, expr2, ...))). The first argument will be evaluated and will be compared against all even arguments (2x) of the function. If it is equal to a particular argument (2x), the next argument (2x+1) is evaluated and returned. Otherwise, the first argument is returned. For example,CASE(2, 1, 'a', 2, 'b', 3, 'c')will return 'b' andCASE(4, 1, 'a', 2, 'b', 3, 'c')will return 4. - FOR_ALL(array, var, expr): Iterate over each element in the given array and evaluated the given expression, where the current array element is set to the given variable. If the expression evaluates for true for all array elements, return true. Otherwise, return false.
- IS_SET(expr): Return true if the given variable, array access or field access has a defined value (i.e., is set). An error is generated if the given expression is not a variable, array access or field access. Arguments can be a variable, a field access, or an array access as follows:
- IS_SET(x)
- IS_SET(x.y)
- IS_SET(a[2])
- THERE_EXISTS(array, var, expr): Iterate over each element in the given array and evaluated the given expression, where the current array element is set to the given variable. If the expression evaluates for true for any array element, return true. Otherwise, return false.
- THERE_EXISTS(table, x, x.field = ‘value’ && boolean-expression) returns true if in the table there exists a variable x which satisfies the expression x.field = ‘value’ && boolean-expression.
For example, THERE_EXISTS(line_items, x, x.cpq_code = ‘prod-code-x’ && x.a > 20)
Note: A condition such as x.cpq_code = ‘prod-code-x’ needs to be added to filter by the product code because the THERE_EXISTS function would generate an error if it runs on a product that doesn’t have field ‘a’.
5 Examples of MobileForce Expressions
In CPQ Product Rules Condition :
Code snippet
HAS_PROD('7782') && ! HAS_PROD('7779') && (opportunity_type == 'New Business')
(PROD_QTY('7783') > 1 && PROD_QTY('7783') < 50)
HAS_PROD('7789') && (! HAS_PROD('7779') || ! HAS_PROD('7792'))
In Quote UI Layout Form access-control hide-condition
Code snippet
In Quote:
!(HAS_PROD('3709') || HAS_PROD('3712') || HAS_PROD('3706') || HAS_PROD('3714') || HAS_PROD('5409') || HAS_PROD('5410') || HAS_PROD('5408') || HAS_PROD('5407') || HAS_PROD('5413') || HAS_PROD('5414') || HAS_PROD('5412') || HAS_PROD('5411'))
In Generated Docs:
cpq_approval_needed || cpq_approval_in_progress || !contact || is_primary == 'no'
In Layouts: making fields READ-ONLY for specific roles: Note the use of single quote (') to demarcate roles since roles can have blank spaces.
ACLMATCH(‘role1’)
!ACLMATCH(‘role2')
ACLMATCH(‘role1 | role2’)
ACLMATCH(‘role1 & role2’)
In CPQ Pricing Rules Condition
Code snippet
benefits_pricing == 'minimum'
is_network_opportunity == 'yes'
In Approval Rules and Approvers
Code snippet
term_years == '4' || term_years == '5'
ARRAY_MAX(line_items, 'cpq_user_discount') > 40 && (!HAS_CAT('Advanced Service (NR)')) && (!HAS_CAT('Advanced Service'))