/
Working with Rules

Live Forms v7.4 is no longer supported. Please visit Live Forms Latest for our current Cloud Release. Earlier documentation is available too.

Working with Rules

Business rules are added by editing your form or workflow. Click the Rules icon in the form/flow designer toolbar to add new business rules or edit existing ones.

provides two ways to create business rules:

  • Visual Rule Builder - visual wizards to help create your rule. The Visual Rule Builder provides access to the generated JavaScript in the Rule Validator for editing.
  • Rule Validator - canvas to type in JavaScript with tools to help form/flow designers write and debug rules.

Create a new rule by clicking on the icon. 

Each rule has two icons:

  • Click the  icon to choose the Visual Rule Builder or the Rule Validator canvas to add a new rule or edit an existing one.
  • Your new rule is given a randomly generated name. Change the name and description to describe the rule function.
  • Rules are enabled by default. They can be temporarily disabled by unchecking the Enabled checkbox.
  • Click the Run Builder button to open the Visual Rule Builder (Click the link to find out more information about the wizard) or the Rule Code button (Click the Rule Code link for details about the Rule Validator) to enter the JavaScript directly. 
  • Click the icon to delete a rule. Confirm your choice in the dialog that pops up and the rule will be immediately removed. This is an irreversible process so make sure you do not need the rule before you delete it.
  • Click the to test your rule without leaving the Rule Editor
  • Click the View All link to see a readonly list of all the rules in your form/flow.

Refer to Rules Examples for many real world samples.

 On this page:

Writing Rules / Syntax

A business rule is created as a piece of JavaScript code. The Rules Builder provides a wizard that generates the JavaScript for you or you can enter the code directly into the Rules Validator canvas. Either way, rules are saved and runable after you commit your form.  In order to test a rule you must first commit your form. Then test it in use mode by clicking on the icon.

A rule is of the form:

if (condition) 
{    
    true actions;
} 
else 
{   
    false actions; 
}

You can create more advanced rules primarily for the purpose of looping over repeating items. We will describe these later in the many rules examples below.

Some basic concepts of JavaScript:

  • Everything is case-sensitive. Ex: var color1 and var Color1 are two different variables.
  • Variables are loosely typed. Ex: var color = 'red'; and var num = 33 case the variable color to be a string type and num to be a numeric type.
  • End-of-line semicolons are optional. However we recommend you use semicolons to terminate lines as part of proper coding practice as this often prevents mistakes. Also the rules validator will flag missing semicolons as an issue. So do add them to your lines.
  • Comments. Code can be commented out using either // or /* */ syntax

Rules do not currently support the syntax:

  • switch statement

Rules support the following syntax with some limitations:

  • try-catch

Example: The value of the control named FN will get set to 'got exception' because the JavaScript variable named x is undefined in this rule.

if (form.load) {   
    try {     
        x.randomproperty = 'blah';   
    } catch (e) {     
        FN.value = 'got exception';   
    } 
} 

However, catching an exception when a  control does not exist (is undefined), will not work as you might expect. This is because  catches the problem while parsing the rule before the JavaScript interpreter catches the error. In the example below the control named Color does NOT exist in the form.

if (form.load) {   
    try {     
        Color.value = "red";   
    }   catch(e) {     
        msg1.value = "error caught: " + e;   
    } 
}

Strings vs Numbers

Because JavaScript is a loosely typed language you may run into occasions where you are trying to add field values and the rule performs string concatenation instead. There are several ways to designate math vs string. One simple way is by adding a *1 to the variable. id = id*1 + 1; will ensure that id equals the current value plus one rather than the current value with a 1 appended. Ex: If the current value was 4 and you didn't write id*1 the result may be "41" rather than 5.

You may also encounter a situation in a rule in which money controls perform a string concatenation rather than addition. To correct this:

  • Open the form with the rule in the Designer, change the money controls to text controls, and then save the form.
  • Open the form, change the text controls back to a money controls, and then save the form again.

See this topic about string and numeric conversion.

Writing Conditions

One of the most common conditions is a rule that executes as soon as the user enters a value in control. The test for this condition depends on if the field is a string type or a numeric type.

String Types: text, textarea, date, phone

if (name.value.length > 0) 

Numeric Types: money, quantity, number

if (name.value != null) or if (name.value > 0) 

are both common test conditions.

Many times the condition name.value.length > 0 can be dropped altogether and the rule can be simplified. This rule executes whenever a user enters a value into either the control named firstname or lastname because the firstname and lastname controls are on the right side of the assignment operator.

fullname.value = firstname.value + ' ' + lastname.value; 

Conditions testing for equality should use the === operator and not the ==. The latter will not pass the validator's strick syntax verification even though it may perform correctly at runtime. It is a good habit to always use ===.

if (Age.value === 13)

Use caution when switching == to === as the latter removes the type coercion. For example, dropdown, radio and checkbox control values are text types. So you must quote values when performing comparison operations:

Ex: if (Building.value === 1) will evaluate to true. You must quote the 1 as in if (Building.value === '1') to make the one a text type.

Control Name

Rules usually need to reference form controls. You assign a control a name using the control's name property.

  1. Names are case sensitive. If your control is named FirstName then you must write the rule as FirstName.value. firstname.value will not work.
  2. Use English alphabet characters only when naming controls. For example, controls named with ó as in Póliza may cause issues when the control is used in a business rule and with submission data.
  3. It is highly recommended that you avoid using JavaScript Reserved Keywords as control names.  For Example, a section named New in your form will cause rule validation errors if explicitly referenced in a rule. Your rule may still work but the only way to fix the error in the rule validator is to change the name of the control. Click here for a list of the JavaScript Reserved Keywords to avoid.

Duplicate Control Names

It is very important when using a control in a rule that the control has a unique name. If multiple controls have the same name  can not determine which control the rule refers to. Controls added to your form from palette are for the most part forced to have a unique name. If you try to change it to a name of a control that already exists in your form  will not allow it. However there are several ways you can have multiple controls with the same name:

  •    Controls added from XSD data sources
  •    Controls added from the custom palette
  •    Controls nested in Sections

For example, when a control is dropped inside a section control, it is at a different nesting level then a control dropped outside a section. Also two controls, one inside a section called Car and another in a section called Boat are also at different nesting levels. The form designer will allow you to name the controls the same. For example both Car and Boat can contain a control named VIN.

You will have unexpected results if non-uniquely named controls are used in rules. Simply edit their names to make them unique. Note that editing the name of a from xsd schema control has no effect on the xml instance document created when the form is submitted nor on the xml validation.

The rule validator described in detail below will help you detect this potential rule bug by displaying a validation error such as the one shown below. This form has two controls named HorseName.

Accessing Control Properties

Rules refer to form controls using the control's Name. Let's say you have a control which you named FirstName. You can refer to properties of this control using the syntax <Control Name>.<Property>. The current version of , supports the following properties:

  • visible : Set to false to hide a control and true to make the control visible.
  • value : Read or write the value of a control. This is not applicable to sections, tabs and other controls where it does not make sense to set a value.
  • enabled : Set to false to disable (grey out) a control so that a user can not change its value and true to enable it. This is not applicable to sections, tabs and other controls that do not make sense to disable/enable.
  • expanded : Set to false to collapse a group control (sections controls only) and true to expand a group control.
  • selected : Set to true to make a tab the selected tab (tab controls only).
  • valid : The value of this property is true if the control contains a valid value otherwise false.  Validity is based on the control’s type.  For instance a numeric control will be invalid if the user enters a string value that cannot be converted to a number.  This property can be read as well as written.
  • required : Set to true to make a control required and display a yellow background color. Available for palette and schema controls (controls generated from XSD schema data source). This is also a property of section controls. Setting a section required to false automatically sets all inner controls to not required. Click here for an example.
  • options : This property enables dynamic setting select control options (radio, dropdown & checkbox controls only).
  • label : This property sets the label seen on any control including sections.
  • help : This property sets the help text.
  • hint : This property sets the hint seen on hover.
  • status : This property sets the error message display whenever the control's value is invalid. The one exception is the Required Property for Controls in an Accessible form/flow.
  • clicked : This property works with trigger controls.  Its initial state is false.  When a user clicks a trigger its state turns true.
  • printable: Set to false to remove the control from both the printable view and PDF submission document.
  • itemAdded : This property works with repeat controls.  Its initial state is false.  When a user clicks "+" to add a repeat item AND when a repeat item is added via a Document URI as the form loads its state turns true.
  • itemRemoved : This property works with repeat controls.  Its initial state is false.  When a user clicks "-" to delete a repeat item its state turns true.
  • itemIndex : This property works with repeat controls. When an itemAdded or itemRemoved event fires the value of itemIndex is set. For itemRemoved events itemIndex will return -1. For itemAdded events itemIndex will give you the index of the added item
  • minFiles - This property only applies to an Upload control. Use this property to dynamically change the minimum number of attachments that can be uploaded by the user.
  • maxFiles - This property only applies to an Upload control. Use this property to dynamically change the maximum number of attachments that can be uploaded by the user.
  • comment.value - This property only applies to dropdowns, checkboxes and radio controls. Use this property in a rule to retrieve or set the value of the comment field that displays when users select the last option. The comment value can also be accessed for dropdowns, check boxes and radios directly in templates using special syntax.

Examples of identifiers used in  rules are:

  • FirstName.value
  • BillingAddress.visible
  • Email[1].value 
  • Email[i].visible

 

The latter two are examples of repeating controls. We discuss repeating controls in more detail below. Note that the case of the properties is important. FirstName.value is a valid rule identifier but FirstName.Value and FirstName.vAlUe are not.

Events

There are three special events that do not reference a specific control name. They use the static name "form". Rules can be written based on when these events occur. See Rule Examples for many use cases referencing these events.

  • form.load : This event is occurs when a form or workflow step loads for the first time. It is useful for setting default values via rules that you need to be set before the user starts interacting with the form. 
  • form.unload : This event is true when users click the form's Submit or a flow's Continue button. It is useful for setting control values just prior to the execution of the form's Doc Actions and Form Actions. If you have a rule in your form that changes any control(s) after clicking Submit, thereby making the form invalid, the form will no longer be submitted and the invalid form will redisplay. Form and Document actions will not execute,  PDFs are not generated, invalid controls become highlighted as expected and form.unload output displays in the debug console. This prevents an invalid xml for a successful submission from being created and only applies to forms.
  • form.positionUpdated : This event is used for the Geo location feature. You can fire a rule using this special identifier every time the position is updated.
  • form.activate: This event indicates that a flow has navigated to a step. If form.activate is true, the workflow just moved to a step. Use the _data.getParameter to determine what step that is.
  • form.deactivate:  This event indicates that a flow has left a step. If form.deactivate is true, the workflow just left a step. Use the _data.getParameter to determine what step that is.

form.load vs form.activate

The form.activate and form.deactivate events can be used in rules in forms and multiuser flows but they are most useful for screenflows with regards to forward/backward navigation. Flow designers often need to orient rules around flow navigation. For example, you want to do something when your flow moves from step 2 to step 3 or you want to do something when you are leaving a step.

A form.load event fires only when the form initially loads and cannot be used reliably for setting the form state to ensure proper flow navigation when a user navigates back and forth via the Navigation toolbar. Designers must take care to avoid a situation where a step in a flow becomes invalid thereby prohibiting forward navigation.

For example, imagine a two step screenflow created using linked steps:

Step 1 has 2 text controls, both are not required and text 2 is hidden. The flow has a rule that makes text 2 required and visible when the flow navigates to step 2.

  1. The user access the flow, the form.load rule runs, text 2 is not visible and not required. The user completes step 1 and hits continue. The flow advances to step 2.
  2. On step 2, text 2 becomes required and visible.  
  3. Without filling in text 2, the user navigates back to step1.
  4. On step 1, text 2 is not visible but the control is required and the flow will not advance when the continue button is clicked.

form.activate and form.deactivate give designers a more reliable way to set properties appropriately for each step in a single user screen flow. This is helpful when considering back and forth flow navigation in order to prevent invalid flow states as described above. Writing the rule with the form.activate identifier instead of the form.load resolves the issue.

Users must be aware that in general, form.load is a one-time event that fires only when the form is loaded the first time while form.activate fires every time a Read/Write form is shown.

The difference between form.load and form.activate is:

·         For READ/WRITE FORMS IN FLOW (the steps in a single user screenflow):

    • form.load fires once when the form is instantiated.
    • form.activate fires every time a R/W form is displayed (including the first time when it is also instantiated).

·         For READ_ONLY FORMS IN FLOW (the steps in a multiuser flow):

      • form.load fires once when the form is instantiated.
      • form.activate does not fire at all when moving backwards to a step performed originally by another user.
      • The step assigned to the current user will load only once but will activate every time they are loaded in a particular session.

It is important for the designer to understand when these events fire in order to make an informed decision about when to use form.load vs form.activate. Certainly, there are situations when you might want to run a rule when the form loads. For example, you may want to prefill fields with user details or populate the options of a dropdown from your database or Google sheet.

form.load is triggered in the following situations:

  • When the first step in a flow is displayed.
  • Navigate to the next step in a screen flow for the first time
  • Perform the next flow step from the task list
  • Save a form/flow  and perform from the task list
  • Edit submission
  • Navigate back to prior flow steps while editing a submission for the first time

form.activate is triggered when you

  • Navigate forward/backwards whether it’s the first or nth time in a screen flow
  • Will not trigger when navigating back to a read only step.

When you edit a submission:

  • The last activity loads and activates when initialized
  • Navigating each activity would both load and activate it.

When a form is saved and then loaded from the task list both load and activate are triggered.

Here is an example of a single user screenflow where a rule was written based on a form.load event when the form.activate event was a better choice.

form.unload and form.deactivate

  • These two identifiers are identical - whenever a step gets deactivated, it is unloaded as well. form.deactivate was added for completeness.

Using the Form Outline

When writing rules, it is critical that you refer to your form's controls using correctly spelled control names, correct case and that you refer to the control properties applicable to the control's type. For example only section controls support the expanded property and only radios, checkboxes and dropdowns support the options property. The Form Outline assists form designers by making all the form's control names visible where you can copy/paste them into your rules. Also the Form Outline displays a properties list so you do not have to memorize the documentation above describing which properties are applicable to which control types.

The Form Outline is only visible when you toggle to the business rules designer view. When you toggle back to the form designer canvas view the Form Outline is hidden.

At first the form outline will be collapsed. Click the "+" on the top level form icon to begin expanding the outline. The icons are indicative of the control's type. See the LoanDate control displays a calendar icon and the LoanNumber is a quantity control. The BorrowerInformation, LoanTerms and SubjectPropertyInformation controls are section types. You can click the icon to copy a control name from the outline. The image below shows the light box that displays and prompts you to copy the control name to the clipboard via Ctrl C or Command C. From the clipboard, you can paste it into your rule. This is a great way to avoid typo mistakes.

Continue expanding the outline by clicking deeper "+" icons to reveal controls nested inside of panels and sections. In this example the Subject Property Information section contains a Panel40 and an inner Panel44 with a dropdown control named State. Notice that the outline shows all the dropdown control's options in value=label syntax. This is very useful when you need to perform a comparison to determine which option a user selected. You can copy/paste the option values into your rules to avoid typo mistakes by clicking on the icon to the right of the options. 

Every control has a Properties icon. Click the "+" to expand the Properties. You will see a list of all the properties that are applicable to this control. Note that even the "form" itself has a Properties icon which show that the form has form.load and form.unload properties. LoanNumber is a quantity control and thus has all the properties you'd expect for this control type such as LoanNumber.required, value, visible, etc..

Refer to Rule Editor Functions  for an alternative method of composing rules within the rules editor.

When are Rules Executed ?

When you create or edit a rule,  figures out the list of controls and properties of those controls that the rule depends upon. The rule will be automatically executed whenever there is a state change that is relevant to the rule. This is called a dependency. If there are multiple rules triggered by the same dependency, the rules are executed sequentially in a top to bottom order as they are seen in the form designer's rules panel.

Rules can trigger the execution of other rules. So, if a rule, R1, sets the value of a control with Name A, and there is a rule R2, that depends on A.value, then rule R2 will be triggered and executed.

A rule will typically refer to one or more form controls and their properties and it will be executed if any of those properties change value. Note that Rules are not fired when the page is loaded. See form.load for more details. For example, the rule below will only be executed when N1.value changes its value.

if (N1.value > 0 || N2.value > 0) {   
    T.value = N1.value + N2.value; 
} 

 Now let's assume a use case where you want to show a message if a user enters an invalid email. The form has a required email input control (Name=E) and an action should be executed if the email control 'valid' property is 'false'. One could write the rule:

if (!E.valid) { 
// code to show message here. 
} 

The code above would not work as expected. E is a required field and therefore E.valid initial value is 'false' since the field is in initially empty. When the user enters an invalid email address, E.valid would still have the value 'false' and the rule would not execute since there is no state change. The code below would work properly.

if ((E.value.length > 0) && (!E.valid)) { 
// code to show message here.
} 

Now, the rule depends on both the value of E.valid and E.value.length and therefore, when a string longer than zero characters is entered the rule will be executed and the message will be shown.

Infinite Loops

It's easy to create rules that run forever. An example, is a rule that updates A.value based on B.value and another rule that updates B.value based on A.value. They could continually trigger each other.

The  server will prevent this from happening by setting an execution time limit for each rule. Any rule that takes longer than 5 seconds to execute will be forcibly stopped. Note that this is a very lengthy period of time for most computational tasks and the vast majority of rules will not be impacted by this constraint. However, since  is a hosted site that may be simultaneously used by numerous users, there is a time limit imposed on these computations.

Circular Dependencies

The restriction to disable rules with circular dependencies has been lifted. For example, the rule below tries to set the value of the same control used to trigger the rules execution. 

if (Users.value < 2) {
  Users.value = 2;
}

Where are Rules Executed?

Business rules are executed on the  server-side and not as client-side javascript. There are several reasons why rules execute server-side:

  • Browser independence. We found it impossible to get these to run reliably in so many versions of so many browsers, especially IE. A bug in your rule (e.g. an infinite loop) will crash the browser and in some cases will require a Windows reboot. On the server, these run in separate threads with lower priority and timeouts so it will not impact the form server.
  • The ability for the rule to do server-side things like http:get () to a database connector, invoke a REST service etc. These often reside behind the firewall and are not accessible to the browser.
  • The rules are not exposed to the browser at all so any sensitive information in the rule (e.g. a password) won’t leave the server. However, we do not recommend putting any sensitive information in a rule.
  • Rules can use information like the currently authenticated subject user id, name, email etc. though technically it would be possible to make this available on the browser if required. However, providing this information in the browser is a potential security hole.
  • Rules can also modify a control – in theory, this can cause large-scale changes to the form’s valid state. Think of an optional XML complex type that has a deeply nested data structure inside it with some required and some optional elements. If any element has a value, all the other required elements become required. It’s much easier and efficient to analyze the form on the server although, technically, this is also possible in the browser. It can be extremely slow for large forms, especially in IE or if someone is running on a slower machine.

There is a potential for performance bottlenecks. However, this is rare since rules are not compute intensive typically. We think the benefits outweigh the drawbacks here.

Dates and Times

There are several special considerations when writing rules using date, time and date/time controls. You can also find many working samples in the Rules Examples chapter.

To initialize a date control, the data must be in the correct format. Here are examples of correct date formats:

d1.value = "2012-01-13"; //yyyy-mm-dd
d2.value = "01-13-2012"; //mm-dd-yyyy
d3.value = "jan 13 2012"; //using string for month

 The following formats will not correctly initialize a date control. They will either cause unexpected results or be flagged as an invalid value when the form is used.

//adjusted or invalid date formats
d4.value = "2012-13-01"; //yyyy-dd-mm
d5.value = "13-01-2012"; //dd-mm-yyyy
d6.value = "13-2012-01"; //dd-yyyy-mm
d7.value = "01-2012-13"; //mm-yyyy-dd

In general, it is not recommended to rely on either the browser's locale or the server's locale when writing date, time (time of day) and date/time literals in  rules. The recommended method is to use locale independent formats that are listed below. These are standard ISO formats.

Date - yyyy-MM-dd

Date/Time - yyyy-MM-ddTHH:mm:ssZ - The trailing Z indicates UTC.). 

Time - HH:mm:ss (or HH:mm). Time is really time of day and is not affected by time zones at all.

yyyy-MM-ddTHH:mm:ss is also supported but will convert to the server's timezone. The rule author has no control of this, so it is not recommended.

Here is an example rule:

if (form.load) {
  date.value = "2012-02-29";
  timeofday.value = "13:10:02";
  datetime.value = "2012-02-29T18:10:02Z"; 
}

This rule will initialize a date control in a form with 02-29-2012, a time control with 1:10 PM and a date and time control with 02-29-2012 in the date portion and 1:10 PM in the time portion.  

Notice the special character "Z" at the end of the date/time value. This is equivalent to an offset of UTC-00:00 and indicates that the time of 18:10:02 is given in UTC. 18:10:02 UTC is equal to 1:10 PM Eastern Standard time. 

Timezone

Time and date/time controls also require correct formatting and an understanding of how  manages timezones.  converts times into the browser's local timezone before displaying them in the form. However, if time data is not correctly formatted  will make multiple attempts to parse the time but will always display the time with NO timezone conversion. Here are examples of correct time formats:

t1.value = "20:30:00";
t2.value = "20:30:00Z";
t3.value = "20:30:00-04:00"
dt1.value = "2012-08-23T20:30:00";
// Also any combination of valid date and time formats.

In the examples above, t2 uses the special "Z" character to specify UTC timezone and t3 uses the offset timezone method by adding a -/+ offset from UTC. -04:00 is the EDT summer timezone or otherwise known as America/New_York. dt1 is a date/time control and must have the "T" character separating the date part of the string from the time part. Any combination of valid date and time formats are allowed for date/time controls. Finally t1 does not specify a timezone so  assumes the browser's timezone. If the browser is running in EDT America/New_York, then "20:30:00" is equivalent to "20:30:00-04:00". So, in this case t1 and t3 in the above example would display the exact same times.

The following time formats are incorrect. Though the time and date/time controls get initialized, no timezone conversion occurs.

// BAD time formats
DateTime.value=["2011-8-23","20:20:20"];
Time.value="20:30";

The time control is independent of any timezone and simply displays the value as is. The time value should not shift no matter which timezone (or DLS effect) you are accessing it from.

 automatically converts the displayed time for date/time controls to the browser's local time zone. There is no conversion for only date or only time controls. Here are some examples to clarify proper time initialization and expected displayed time. Also refer to the chapter Initializing Forms with Data for date, time and date/time controls.

In the following examples the brower's timezone is UTC-05:00 which is the winter timezone for America/New_York.

In this rule the time data is specified as UTC-05:00. Thus when the control named date/time is initialized with a date of August 23rd, which falls in the summer UTC-04:00 timezone, the time gets converted and displayed as 21:20:20, one hour ahead. The Time control is not converted since time only controls are not affected by timezone. If a user enters 20:30:30 into a time only control it will always appear as 20:30:30 even if viewed by a browser in a different timezone.

if (ESTOffset.clicked) { // UTC-05:00 (winter)
  Date.value= DateUtil.today();
  DateTime.value="2012-08-23T20:20:20-05:00";
  Time.value="20:30:30";
}

In this rule the time data is specified as UTC-04:00. The date/time control has no conversion since August 23rd falls in UTC-04:00 timezone. The control named Time is not affected by the timezone so it displays whatever is specified in the rule.

if (EDTOffset.clicked) { // UTC-04:00 (summer) 
  Date.value= DateUtil.today(); 
  DateTime.value="2012-08-23T20:20:20-04:00"; 
  Time.value="19:30:30";
}

These two rules both specify the time data in UTC timezone because the special character "Z" is equivalent to an offset of UTC-00:00. The Time control is not affected by the time zone so it displays the value specified in the rule data. The date/time control is a date of August 23rd, which falls in the summer UTC-04:00 timezone so the rule data is converted and displayed as four (4) hours behind UTC.

if (ZOffset.clicked) { 
  Date.value= DateUtil.today();
  DateTime.value="2012-08-23T20:20:20Z";
  Time.value="15:20:20";
}
if (OOOO.clicked) { 
  Date.value= DateUtil.today();
  DateTime.value="2012-08-23T20:20:20-00:00";
  Time.value="15:20:20";
}

This rule has incorrect UTC syntax. The Time control initialization is missing the required seconds and the date/time control is using an array syntax that is not a valid UTC time initializer.  makes an attempt to parse the times and does fairly well in this case. But due to the incorrect syntax the date/time control's timezone is unknown and the rule is unable to do the proper conversion to the brower's timezone. The Time control's value is ok as it is not affected by timezone. The date/time control's value is clearly wrong as the browser is running in UTC-05:00 while August 23rd is in daylight savings time UTC-04:00. 

 
if (NotUTCSyntax.clicked) {
  Date.value = DateUtil.today();
  DateTime.value = ["2011-8-23","20:20:20"]; // Array Syntax is not valid
  Time.value = "20:30"; // Missing required seconds
}

Rule Debugging

There are several tools to help form designers write and debug rules. Each is described in detail below.

  • Save and Test
  • Rule Validator
  • Form Outline
  • Debug Console

See the FAQ - Business Rules topic for additional important information and known limitations with rules in the current release.

Save and Test

When you are designing a form/flow with many objects and a lot of business rules, reduce the number of page reloads when switching between the designer view, rules view, and the test view by clicking the save and test icon. Save and Test checks for Rule errors before the test popup displays. If rule validation errors are detected, the designer is notified and given the option to correct before the Test popup is displayed.

If you clicked the save and test icon from the Rules page, clicking Cancel on a Rule Validation Failure message returns to the Rules page where you can make changes. Clicking Ok proceeds to the Test popup. Refer to Testing Forms and Testing Workflows for more information.

Rule Validator

The first step in debugging your rule is to correct all errors caught by the rule validator. The validator executes automatically as soon as you leave a rule input window either by tabbing out of the input, clicking away from the rule to the control view, clicking the form designer finish button, etc... All rules with errors are highlighted in red. If you click finish to save your changes while there are invalid rules, you will be prompted to save with errors.

Not all errors can be detected by the rule validator. It is still very important to test your use mode forms. Use the debug console described in the next topic to test for and solve runtime errors.

Here is an example of a validation error. Note the red background and the validator information displayed below the rule. In this case the control name was mistyped as Yourage when the name is actually YourAge. Remember that control names are case sensitive. So Yourage is not the same as YourAge with a capital A. 

Once you correct the control name in this rule and click anywhere out of the rule code input area, the validator automatically runs again and removes the red background warning and also the validation output area disappears as there are no errors to display.

The validator is very picky and enforces high code standards! Some may find this onerous at first but this is a win in the long run as your rules will have far few issues found at runtime.

Disabled rules will not be validated. This can be useful if you are in the middle of writing a rule and want to save the form without validation errors. Disable the rule temporarily. Note that disabled rules do not execute at runtime either.

If you click finish to save the form and one or more rules have validation errors, you will be prompted: "One or more of the rules on this form validated with error(s). It is recommended that you correct these issues before saving. Do you wish to save now?". If you choose not to save, then the editor remains open.

Both dot and square bracket notation are allowed when getting /setting object properties in rules. 

Validation Directives

Directives are available to control how the JavaScript is validated. Directives are placed at the top of the rule code. The directives do NOT effect runtime rule execution. They are solely for communicating object information to the validator so that your rules pass validation.

This common rule paradigm shown in the example below is used to retrieve data from another system such as a database. This rule will cause validation errors since the validator does not have any information about the variable 'x'. The validator therefore cannot say whether or not the members 'resultSet', 'productId' and 'description' are valid.

if (form.load) {
  var x; 
  eval('x=' + http.get('http://localhost:8082/database/products')); 
  var opts = [];
  for (var i=0; i < x.resultSet.length; i++) { 
    if (x.resultSet[i]) { 
      opts[i] = x.resultSet[i].productId + '=' + x.resultSet[i].description;  
    } 
  } 

  Products.options = opts; 

}

The validator will display the following errors and a suggestion that you can solve this error by confirming that resultSet, productId and description are in fact valid members of object x.  To confirm the suggestion copy the validator's suggested member directive into the first line of your rule. Of course if the validation errors are truly errors, then fix them.

You can copy/paste the members directive suggestion from the validation error pane directly into your rule. This corrected rule will pass validation: Note the use of commas to separate the items in the list ( description, options, productId) . Both global and member directives require comma separators to pass validation.

/*member description, options, productId, resultSet*/

if (form.load) { 
  var x;
  eval('x=' + http.get('http://localhost:8082/database/products')); 
  var opts = []; 
  for (var i=0; i < x.resultSet.length; i++) { 
    if (x.resultSet[i]) { 
      opts[i] = x.resultSet[i].productId + '=' + x.resultSet[i].description; 
    } 
  } 
  Products.options = opts; 
}

The validator also supports global directives. Use the global directive to identify additional global objects and functions defined in the execution environment and made available to the rule for which it is not appropriate to include a var statement in the rule code itself. One directive can be used to list all additional globals on a single line. Currently there are no known cases requiring the use of the global directive.  

Rule Editor Functions

The Rule Validator includes an enhanced editor designed to provide an easy experience when developing rules.The rule editor box includes the following features:  

FeaturesDescription
Line NumbersLine numbers in the rule code editor make it easier to correlate reported validation errors with the line of code.
Bracket auto closeType a {, ( or [ and the closing bracket is automatically inserted.
Match BracketPlace the cursor on a bracket and both it and the matching bracket are shown in a matching distinctive color (green).
Syntax Hi-lightingJavaScript syntax hi-lighting with keywords, variables, comments, etc. shown in distinctive colors.
Auto IndentNew lines are auto-indented according to generally accepted code formatting rules.
Code FoldingBracketed code blocks (functions, if-then-else blocks, etc.) are collapsible. Click the arrow immediately to the right of the line numbers to collapse/expand code blocks.
Full screen edit mode

Expand the editor to full screen mode if you need more space to work. Click the "double arrow" expand icon (directly above the editor box) or press F2 when your cursor is inside the Rule box to expand to full screen. The ESC key returns you to small window mode.

Auto Complete/HintingWhen composing a rule, the designer can pick from a list of available controls and their properties directly within the rule editor. The pick list is context sensitive and will behave differently based on where the cursor is located when it is invoked. When on a blank space or immediately following an open bracket/brace, it can be manually invoked using Ctrl-Space to bring up a list of controls. Typing a dot (.) immediately after a  control name or after the index ("[i]") that follows a control name will automatically bring up a context sensitive pick list of properties applicable to that control for selection. You can type the first letter of the item you are looking for and the property starting with that character will be highlighted in the list. Continue typing and the matching options will progressively narrow to the characters typed. Double click your choice using the mouse or press the Enter key to select an item. Any other key dismisses the pick list. . See the example below
HelpThe help icon displays a small help window listing the hot keys described above - (F2, ESC and Ctrl-Space)

Auto Complete/Hinting Example

The easiest way to minimize mistakes in control names when writing rules is to use the Auto Complete/Hinting feature in the rule editor. Let's say you want to compose a rule that will populate the FirstName field in your form with the first name of the logged in user when the form loads. This rule using the Built-in Data in conjunction with the form.load rule identifier will accomplish this.

if (form.load)
{
  FirstName.value = _data.getParameter("subject.first.name");
}

To begin, type " if (" on the first line of the rules editor. The closing parenthesis will be added automatically.

Type "form." - the word form followed by a dot - after the open parenthesis and a list of available identifiers displays. You can type the first letter of the item you are looking for and the property starting with that character will be highlighted in the list. Double click or use Enter key to select your choice. For this example, select load.


Press the Enter key to advance to line 2. Add the left curly bracket. Press the Enter key to advance to line 3. Press Control Space. A list of available controls from your form will display. You can type the first letter of the item you are looking for and the first field name starting with that character will be highlighted in the list. Be sure to use the correct case. Double click or use the the Enter key to select the FirstName control. The control named FirstName will be inserted in your rule.


Type a "." after the control name to see the list of available properties that can be used in a rule for this control. You can type the first letter of the item you are looking for and the property starting with that character will be highlighted in the list. Be sure to use the correct case. Continue typing until the value property appears in the list. Double click or press the Enter key to add it to the rule.

Add the remainder of the rule. The closing bracket will already be there.

Correct any other errors reported by the validator. Click anywhere outside the editor to verify there are no further errors.

Click the save and exit icon to save your rule.

Of course, you can still use the Form Outline to help you when composing rules.

JavaScript manually entered into the Rules Editor is not autoformatted. JavaScript "beatification is only applied to rules created with the Visual Rule Builder. 


Debug Console

The debug console can help you quickly solve runtime problems in your business rules. The debug console is enabled by appending the URL parameters _test=true and embed=true to a form's share URL. A form's or flow's test button automatically adds the &_test=true parameter so you do not have to append the parameter manually. The debug console appears below the form. If your form is long, scroll down to view the debug console.

Here is an example of the Share URL (Link/Email/Web) that will display the debug console for the form in the image when browsed. Note the _test=true is preceded by a ? to separate the form/flow URL from the parameters. Subsequent parameters, such as the embed-true parameter, are preceded by the & to separate the parameters from each other. Refer to Parameter Separators in URLS for more information about this syntax.

https://app.frevvo.com/frevvo/web/tn/mycompany/u/8aa27da6-4bef-427c-92e3-6ad8d58e506a/app/_QDidgGGwEeeZjNWktbplXA/formtype/_tZmTYFf-EeeDC8g6jZAQlw/popupform?_test=true&embed=true

The debug console will only appear for users that have the special frevvo.Designer role. If a user without frevvo.Designer role appends the &_test=true URL nothing will happen, no debug console will become visible. This protects the designer's rule code from accidentally becoming visible to normal form/flow users.

The rule validator will catch many of the common errors you can make writing rules but it will not catch all errors. Some issues are only caught by testing your form at runtime. For example if a rule reference a control that repeats but the rule does not use the necessary repeating array syntax, this will pass validation but can be caught by runtime testing with the aid of the debug console.  

Here is an example of debug console indicating that there is an error in the rule due to the fact that there is not control name 'TID' in this form.

The most recently executed rule is displayed at the top of the console. Scroll down to see prior rules. To follow a rule's execution, scroll down to find the RULE_START Event and then read the console output from bottom to top. This ensures that the latest rule output is always in the most handy position at the top of the debug console area.

The debug console is organized into 5 columns:

  • # -  A sequential line number. The # starts at 0 when a form is instantiated and increments until the form is finally submitted. Even if you clear the console by clicking the Clear link, the numbers continue incrementing from where they left off for this particular form instance. This gives you a clear way to follow the order in which the rule code was executed during the lifetime of a particular form instance.  
  • Level - One of 5 log levels. See below for details. The level also dictates a color coding. For example all ERROR log level messages are displayed in red.
  • Event  - One of many possible Events. This column enables you to quickly distinguish between various events such as rule start/stop. See the detailed event list below.
  • Source - This column contains the name the designer gave to each rule for RULE_START and RULE_END events so that you can clearly see which rule the output lines are a part of. Source is also set for DOC_READ_START and DOC_READ_END events and indicates the name of the data source. If the data source is the default document Source displays the form/flow's name. 

Refer to the  log files for a complete history of all rule debugging output. 

Log Levels

The debug console log level output defaults to the most verbose level which is TRACE. Currently there is no way to change this. The output is color coded with ERROR messages appearing in red so they can be quickly identified. The recognized log level are:

  • ERROR
  • INFO
  • DEBUG
  • VERBOSE
  • TRACE

The log levels are inclusive. For example: INFO level includes ERROR, DEBUG includes INFO, etc.

This rule executed successfully as no ERROR level log messages appear in the console. The TRACE level output includes RULE_EVAL events which dump the exact lines of Javascript in your rule.

Event Types

The Event types enables you to quickly understand the meaning of each line in the debug console output. The event types are:

  • START - signals the start of an execution that may span one or more rules and Doc URIs 
  • END - signals the end of the execution of a batch of one or more rules plus the total execution time in milliseconds
  • ERROR - any errors that were thrown NOT in the context of executing rules
  • START_RULE - signals the start of a rule execution
  • END_RULE - signals the end of a rule execution plus the execution time of this one rule in milliseconds
  • RULE_ERROR - any errors that happened while executing the specific rule
  • RULE_EVAL - A message displaying the rule script
  • RULE_DEP - one for each rule dependency. Examples of dependencies are: form.load, trigger clicked, if conditions that trigger rules, control values changes on the right hand side of assignments, etc..
  • RULE_SCHEDULE - shows the next rule to execute and the remaining rules in the agenda/batch. This event makes it a bit easier to track what the rules engine is doing when debugging.
  • PROPERTY_SET - one for each control property set by the current rule
  • HTTP_START - signals the start of an http call (get, put, ...)
  • HTTP_END - signals the end of the http call + status code and timing
  • HTTP_RESPONSE - a message that dumps the first few lines of the http response
  • HTTP_ERROR - any errors that may have been thrown while performing the http call
  • DOC_READ_START - signals the start of a manually set Doc URI read
  • DOC_READ_END - signals the end of a manually set Doc URI read
  • DOC_READ - signals the success or failure of the Doc URI read
  • LOG - a user defined message that can be generated from a rule using frevvo.log('my INFO message') or frevvo.log('DEBUG', 'my debug message')
  • INFO - this statement informs the designer when the set of property values in a flow during form state initialization are ignored.
  •  WEB_SERVICE - events to report the URL and XML/JSON results when dynamically populating selection control (Dropdown, Checkbox, Radio and ComboBox) options from a RESTful web service
Dynamic Options Logging

Populating a selection control (Dropdown, Checkbox, Radio, ComboBox) using the Dynamic Options feature, requires the designer to examine the returned results from an entry point to determine bind paths, troubleshoot end point urls, etc. To assist the designer when developing forms/flows with controls that use this feature debug console logging includes Web Service events such as:

  • The web service call being made with fully the resolved end point URL shown
  • The web service data retrieved (JSON/XML)
  • Any errors received upon calling the web service.

Refer to the Dynamic Options topic for an explanation of this feature and examples of how these web service events in the debug console assist the designer.

Custom Output

This example shows a CUSTOM event. These events are created by adding frevvo.log() calls to your rules. Custom log messages are useful when you need even more debugging output. See Custom Logging for more details.

 

Doc URI write methods information, which occurs when the form is submitted, do not appear in the debug console output.

Rule Debug Logfile Output

Rules debug output can also be written to the  log file <frevvo-home>/frevvo/tomcat/logs/frevvo.log file and is also visible in the tomcat console if tomcat stdout logging is enabled.

To change the rule debug logging verbosity level, append one of the Url parameters below to the  base url. For example: http://<server:port>/frevvo/web?rule-debug=TRACE turns on the highest rule debug log level.  The verbosity options are:

    • ?rule-debug=ERROR - Only log errors
    • ?rule-debug=INFO - A moderate level of logging is output
    • ?rule-debug=DEBUG - A higher level of logging is output
    • ?rule-debug=VERBOSE - Rule dependencies and the rule code itself is also logged
    • ?rule-debug=TRACE - This is the most verbose rule log level

Log levels are inclusive: INFO level includes ERROR, DEBUG includes INFO, etc

Changing the rule logging verbosity affects all tenants, users, and forms running on the server. A high log level can effect the form server's performance. Turn rule logging back to the lowest level of ERROR when your are done debugging.

Rule Profiling 

Rule execution can be profiled to determine how much time each rule takes to execute. This can help you tune and improve performance in forms that use a lot of business rules. To turn on profiling in the log files set the rule-debug=INFO or higher. See rule debugging for setting log levels. Profiling output is also displayed in the Debug Console.

The execution time for each rule is displayed on the RULE_END and END events. This sample debug console output indicates that the rule named "Init Products" executed in 125 milliseconds. The 141 milliseconds shown on the END event is the total time for all rules triggered by a single form change event. It's likely that the END event total time will be great then the addition of all RULE_END times. This is normal and due to the fact that some small time elapses between each rule.

 

Rule profiling is very helpful in narrowing down performance issues in rules that execute database queries. Profiling can help you identify if the db queries are taking too long. You will see HTTP calls taking a long time to execute.

As rules are executed on the  server and not on the browser client side. Thus timing is effected by the performance of your server machine and the server's current load.

Rule Timeout

By default a rule that takes longer to execute then 5 seconds will be timed out by the Form Server. Customers using the in-house download version can customize this timeout. This is often necessary when rules have to perform longer running operations such as sending email messages, database stored procedures, etc. To configure the timeout add the following line to your web application containers property file. For the -tomcat bundle this file is <frevvo-home>\tomcat\conf\Catalina\localhost\frevvo.xml and is specified as follows:

<Parameter name="frevvo.rule.timeout" value="5000" override="false"/>

To set the timeout to 15 seconds set value="15000"

Rules and Repeating Controls

If you have a repeating control in a form that itself contains a repeating control, you cannot apply a rule to the "inner" repeating control, since there's no way to tell which of the inner repeating items goes with which outer repeating item.

Dynamic Add or Remove for Repeating Items 

The minOccurs and maxOccurs (Max#) properties of a Table or Repeat control, can be used to write a rule to dynamically change Min# and Max# values of repeating items. Here's how it works:

In the designer, set the min/max properties so that they cover the whole range of min and max numbers that you wish to use via rules. When you increase the Min# value with a rule,  will check if that number of items are there in form, if not then it will add them. When you reduce the Max# via rule,  will check if the form has more than that many number of items. If there are more items than the Max# that you are setting via rule, it will remove those extra items.

This is a way to dynamically change the min and max properties set for these controls in the designer. This feature is helpful if you want to allow only a certain number of items based on user input. 

Follow these important points when writing your rule:

  1. Your rule can set minOccurs to 0 even if the design time setting > 0, but you cannot set minOccurs to a value which is greater than the current maxOccurs.  

  2. Your rule can set maxOccurs to a value that exceeds the design time setting, but you cannot set maxOccurs to a value below the current minOccurs value.

  3. Repeat items and table rows are added if your rule increases the Min# property and are removed when the rule decreases the Max#.

  4. Added rows due to increase in Min# will trigger the itemAdded property. 
  5. This feature can be used for schema controls, but min/maxOccurs values have to be set within the limit given in the schema. For example, if the schema has text control defined with minOccurs=2