Maestro Business Rules

   MaestroThe UI design product.  |   Form Builder |  23.04This feature was updated in 23.04

Maestro allows you to add business rules to components used in a form.

A business rule is a JavaScriptJavascript (JS) is a scripting languages, primarily used on the Web. It is used to enhance HTML pages and is commonly found embedded in HTML code. JavaScript is an interpreted language. Thus, it doesn't need to be compiled. function that is invoked in response to different events related to a component. Developers working in Maestro do not normally see the function scaffold that is provided by the platform, but it is important that developers understand how this works.

Rules are invoked by the Maestro framework in response to:

  • a change in the data object bound to a component,
  • an event propagated from the web browser,
  • an asynchronous event like a Dynamic Data Service, or
  • because a script directly invokes a rule function via an API call.

For example, a Valid If rule is triggered when the data value changes, a Click rule when the user clicks on an element, a Page Load rule every time a Maestro page is shown, and so on.

Rule developers need to understand what is provided by Maestro in the scope of a rule function:

data
is an object passed as the first argument (argument[0]) to the JavaScript rule function.
For non-repeated items, this is the form data object holding values for user defined all form fields plus additional system-related data.
For repeated items, this is a repeating object instance holding all sibling repeating values, including any nested repeats, plus other properties, such as the current index, the repeated data object array and the parent item.
For more information on the structure of the data argument and how repeated data is represented in Maestro’s data model, see Maestro's Data Object.
item
is an object passed as the second argument (argument[1]) to the JavaScript rule function.
An item object contains the structure and definition of the form field including style and properties, as well as repeat-aware getData() and setData() methods.
For more information on the structure of the item argument, see Maestro's Item Object.
info
is an optional object passed as the third argument (argument[2]) to the JavaScript rule function.
The info object contains details of the event that triggered the rule, or the object returned from a success or failure call in a dynamic data service result handler.
For more information on the structure of the info argument, see Maestro's Info Object.
value
is a function scoped variable that is initialized to the value of the data value bound to the item on which the rule was invoked. For example, given an item with the id applicant_firstName, the value variable would be created by the framework as follows:
var value = data.applicant_firstName;
Adding a breakpoint to a rule shows how Maestro generates the function:
Maestro business rule overview
As you can see, this scaffolded references the data argument and so is repeat aware meaning that it represents either the sole data value, or the indexed data value in a repeat.
Calc, DynamicData, EncUtil, Form, HTTP, Insights, Resource, Scroll, Transact, Translation, Util and Validation
are all namespaces that expose Maestro API methods to the form developer. For example, in a rule a developer might use the API method:
Calc.total( data.expenses, "expense" )
Which sums the values of expense properties stored in the expenses array. In addition to this, the API exposes some methods on the global scope.
JSDoc for these APIs is accessed via Maestro by clicking on the API Methods button in a Rule editor:
Or, in the Code editor, by clicking on the API Methods Reference link:

Maestro’s Rule Dialog lists the available rules for the selected item:

Maestro create a new business rule

For more information, see List of Maestro Rules.

You can also create your own business rule types and add them to the Create Rule dialog, and so expose them via the Properties pane. However, these rule types must be for native components only as described in Component Options.

Some components can't have rules added to them, so you won't see the Rules category or any rules displayed in the Properties pane. These components include:

Working with the Rule Editor

The Rule editor is designed to be as simple as possible to use, but sometimes, this leads to unexpected side effects.

Consider a developer who is writing a Calculation rule on a Data Field and needs to inspect the current value and type of the object:

console.info("Value: " + value);
console.info("Value type: " + typeof value);

The console output is:

value: 12

What happened to the second console statement? Why wasn’t it output?

Maestro does not see a return statement and so ‘helpfully’ adds it to the first line of the script. If you were to code this yourself, you would write the following – with the warning because the second line is unreachable:

return console.info("Value: " + value);
console.info("Value type: " + typeof value);

The lesson is that if you write a muti-line rule that expects a return value, you must provide a return statement:

console.info("Value: " + value);
console.info("Value type: " + typeof value);
return value;

When you are developing rules, test your work often in the debugger. Several types of errors, for example compilation problems, can result in your form not displaying correctly in Preview mode.

The earlier you test, the more likely you are to find the bit of code that is causing the problem.

Hints for Rule Developers

Maestro rules are JavaScript and, whereas Maestro hides much of the complexity, rule developers should have a foundation in the language. We recommend the Mozilla Developer Network first steps course.

Maestro Stores Data Values in String Types

All data is stored in Strings which can lead to unexpected results. Consider this rule snippet:

console.info("Value: " + value);
console.info("Item.getData() type: " + typeof item.getData());
console.info("data.income type: " + typeof data.income);
console.info("Value type: " + typeof value);
				
data.income = 678.90;
console.info("Value set to 678.90");
				
console.info("Item.getData() type: " + typeof item.getData());
console.info("data.income type: " + typeof data.income);

Running this rule results in the following output in the browser, with the income in the form field displayed above the developer tools console:

Let's break down what’s going on here:

  1. The value variable shows as 123.45, which was the data entered by the user that led to the rule being triggered.
  2. Internally, the item.getData() returns the data.income property and this is also assigned to the value property – all have a type of string.
  3. This demonstrates that data input into a form is stored as string type by the Maestro framework in the data model.

  4. The rule handler then sets the value via the statement data.income = 678.90. The type of the right hand side of this expression is a JavaScript number. (This could also have been achieved by using a function call: item.setData(678.90).)
  5. Subsequent calls to item.getData() and data.income show that the updated value in the data model has a type of number.
  6. This demonstrates that data input into the data model in a script is stored in the type given.

It should be clear from the above, that rule developers should take care with assumptions about the types they are working with.

Working with Numbers in Rules

If a user inputs a numeric value in an income field and Maestro stores this as a string, how do developers do math?

If we used the data.income property in an expression, you would see an unexpected result. Consider an expression that assumed two numeric values:

console.info("data.income value: " + data.income);
console.info("data.income type: " + typeof data.income);
console.info("data.frequency value: " + data.frequency);
console.info("data.frequency type: " + typeof data.frequency);
				
let yearlyIncome = data.income * data.frequency;
				
console.info("Income: " + yearlyIncome);

The console shows the result:

data.income value: 1234
data.income type: string
data.frequency value: "1"
data.frequency type: string
Income: NaN

Two strings can't be multiplied, hence the result NaN (Not a Number).

There is no magic here – rule developers must learn about JavaScript type coercion, which is the automatic or implicit conversion of values from one data type to another, such as strings to numbers.

To coerce a string to a number, simply prefix the data value with a +, as shown below:

console.info("data.income value: " + (+data.income));
console.info("data.income type: " + typeof (+data.income));
console.info("data.frequency value: " + (+data.frequency));
console.info("data.frequency type: " + typeof (+data.frequency));
				
let yearlyIncome = +data.income * +data.frequency;
				
console.info("Income: " + yearlyIncome);

This gives you the result you expect:

data.income value: 1234
data.income type: number
data.frequency value: 12
data.frequency type: number
Income: 14808
Note

Because rule developers can add any type into the data model, to ensure expected behavior, we recommend that developers performing calculations should always use type coercion.

Converting Data Values to Boolean Values

To force the conversion of any value to a boolean, developers can use a double negation (or double not), namely, !!.

This is a standard JavaScript technique that relies on "truthyness" or "falsyness" of the value. The first ! converts a ‘truthy’ value to false and a ‘falsy’ value to true. The second ! flips these.

This technique is commonly used to check whether an element exists.

Enhancing Form Usability Using Visibility Rules

Consider the case where an application allows single and joint applicants for a product. A form design may wish to only show a text display field when both applicant’s details are known.

To handle this, we would create a Visibility Rule using the technique we just learned:

!!data.applicant1_name && !!data.applicant2_name

JavaScript Techniques that act on Data

If you have, for example, some values in a dropdown list, and want to turn these into more human readable values, you could use an if statement or a switch statement. However, if you want to embed the logic inside some text, you can use the following object key lookup syntax:

{{ {'52': 'per week', '24': 'bi-monthly', '12': 'per month'} [data.frequency] }}

This defines an object with keys 52, 24, and 12 and then looks up the key matching the data field [data.frequency] which, in turn, returns a human readable string describing the value. For more information, see Introduction to Maestro Business Rules.

Having Problems?

If you are experiencing some issues with business rules, learn how to debug them.

Next, learn how to create a rule.