V4 Business Rules

From Frevvodocs
Jump to: navigation, search
Lightbulb.png Rules are probably best learned by examples. See the Rules Examples chapter containing numerous examples and code samples.


Contents

Rules

Overview

Rules add behavior to forms. For instance, you can add a frevvo rule that will show/hide certain form controls or entire sections based on the state of other form controls. Displaying form fields in a context-sensitive manner reduces clutter and makes it easier for users to navigate your forms. Rules can also be used to update form values. For instance, you can compute the total invoice price on an order form from values of other form fields such as item quantity and price.

Working with Rules

In the form designer, click on the Rules tab. The page will display any existing rules that you may have created for this form.

RulesToolbar.png

You may create a new rule by clicking on the Add.png icon. Your new rule is given a randomly generated name. You can edit the name as described below.

Each rule has three icons. Each is described below.

  • Click the Edit.png icon to edit an existing rule. You can edit the name, description and statement (JavaScript code) for the rule.
  • Click the Delete.png 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.

Rules can be temporarily disabled by unchecking the enabled' checkbox. Edit the rule and scroll down below the rule code.

Rules.png

Writing Rules / Syntax

In this version of frevvo, a rule is created as a piece of JavaScript code. A future version of frevvo will provide a Rules wizard that makes it easier to create rules in a visual manner. 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 UseForm.png 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 re optional. However we recommend you use semicolons to terminate lines as part of proper coding practice as this often prevents mistakes.
  • 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 frevvo control does not exist (is undefined), will not work as you might expect. This is because frevvo 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 way tell the rule into 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.

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.

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

Rules Wizard

Future frevvo releases will support a rule wizard making it easier to create rules without needing to understand simple JavaScript expressions and making it quicker to reference controls without needing to first assign them a unique ID. Also at this time rules support a single condition, true action and false action. Future frevvo releases will support multiple conditions and actions.

Control Name

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

18px-Attention niels epting.svg.png NOTE: Names are case sensitive. If your control is named FirstName then you must write the rule as FirstName.value. firstname.value will not work.

18px-Attention niels epting.svg.png NOTE: 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 frevvo 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 frevvo 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

If you have two controls with the same label and at the same level, the control's name will automatically be made unique. If you try to edit the name such that it would no longer be unique, frevvo will prevent the edit. 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.

Rule Identifiers

As described above, rules refer to form controls using a Name. Let's say you have a control to which you have assigned the Name 'T'. You can refer to properties of this control in rules using identifiers.

Rules identifiers must always be of the form Name.<property>. In the current version of frevvo, the following properties are supported:

  • 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 the red asterisk. (NOTE: only affects palette controls and not 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.
  • 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.
  • 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 and 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
  • form.load : This property is true when the form is first loading. 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 property is true when the users clicks the form's submit button. It is useful for setting control values just prior to the form's Doc Actions and Form Actions are executed.

Examples of identifiers used in frevvo rules are:

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

The latter two are examples of repeating controls. We will 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 or FirstName.vAlUe are not.

When are rules executed ?

When you create or edit a rule, frevvo 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. Rules are also executed sequentially in a top to bottom order as they are seen in the rules panel.

Note that 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.ita
}

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 frevvo 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 frevvo is a hosted site that may be simultaneously used by numerous users, there is a time limit imposed on these computations.

Rule Debugging

Rules are currently best debugged via the frevvo logging output. Improved debugging support is coming in a future release. The debugging output can be found in the <frevvo installdir>/frevvo/tomcat/logs/tomcat.log file or in the tomcat console if tomcat stdout logging is enabled.

To change the rule verbosity level, append one of the Url parameters below to the frevvo base url. For example: http://localhost:8082/frevvo?rule-debug=profile. The verbosity options are:

  •  ?rule-debug=quiet - Nothing is printed
  •  ?rule-debug=info - Just Begin Rule / End Rule messages printed
  •  ?rule-debug=less - More information is printed
  •  ?rule-debug=more - Even more information is printed
  •  ?rule-debug=verbose - Parameter values and the rule itself is printed
  •  ?rule-debug=profile - Enables profiling to assist in performance improvements

Note that changing the rule verbosity affects all tenants, users, and forms running on the frevvo server. Turn rule logging back off when your are done debugging.

Rule debugging can help you determine if a rule is unexpectedly repeated multiple times. This can cause performance issues especially when the rule is accessing a database to dynamically populate select control options as the db queries may be taking longer than you expect. (See also rule profiling below).

Using rule debugging you can see if any rules are called more than expected, for example you may have a rule that gets called every time the value of a control on your form is set if the rule uses a <control>.value. This can cause an obvious performance problem. Rule debugging can help you find such performance bottlenecks so you can solve them.

In some cases, by changing the rule priority, you can make sure that the rule with the database call is the first to execute when there are many conditions. For example rule1 call the database and takes a log time, and rule2 has many <control.value> =... that trigger rule1 to be called. If the frevvo rules engine orders the rules such that rule2 executes before rule1, you would end up executing rule1 more than needed.

Debugging Duplicate Control Names

When you're designing forms, frevvo generally prevents from giving controls duplicate names, but you can give controls the same name if the controls are contained within different section controls. For example, you can have two sections in a form named Home and Office, and each section can have a text control name Address. However, if you want to use either of the Address controls in a rule, you have to give them unique names.

One way to tell if a rule is breaking because of duplicate names is to look at the log in the Tomcat console. If you see a message similar to the one below, it's probably a duplicate control name problem.

16:50:35,390  WARN RuleObserver:455 - Error evaluating rule [Translate.Translate
 Form Rule]: Java arrays have no public instance fields or methods named "value"
. ([Translate.Translate Form Rule]#2)
if (form.load) {
  Name.value = 'Nancy';
}

The phrase Java arrays have no public instance fields or methods... means Java is interpreting the controls with the same name as an array, not single controls.

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 set the rule-debug=profile on the frevvo url. See rule debugging for details.

If you rules are executing database queries to populate dynamic select controls (dropdown, radio, checkbox), rule profiling can help you identify if the db queries are taking too long. You will see HTTP calls taking a long time to execute.

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 frevvo-tomcat bundle this file is .../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"

Rule Execution Priority

This experimental features lets you control the order of execution in complex rules usage. There is no UI for this feature. Please contact customer support for information.

An example usage: Rule1 is called when multiple form field values change. Rule2 has many XXX.value = ... that would trigger Rule1. If the rules engine happens to always picks Rule2 to execute first, you would execute Rule1 more than is needed. While rule ordering doesn't cause a behavior issue, if Rule1 happens to perform a more time consuming operation such as retrieving data from a database, this may cause a performance issue. Rule execution priority enables you to tell the rules engine to execute Rule1 before Rule2. Then each subsequent call to Rule1 would be prevented.

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.

What is not permitted in a rule?

Setting the value of a control to an array or to a random JavaScript object is not allowed.

Select Controls

Radio controls, dropdowns and checkboxes are all examples of select controls. Radio & dropdown controls are single select. That is, if one item in the dropdown is selected then all other items in the dropdown are deselected. The same is true for a radio. Only one radio button can be depressed at any time. Thus the ID.value of radios and dropdowns are similar to the other input and output controls. The value is a single item.

Checkbox controls are multi-select. That is, multiple items can be selected at any given time. Thus the ID.value of a checkbox is an array. Therefore on checkboxes a valid expression is ID.value.length which returns the number of items in the value array. And ID[0].value would retrieve the 1st item in the list and ID[1].value the 2nd and so on. If you have a checkbox control with only one checkbox and that checkbox is unchecked, the array will contain no elements. For an checkbox control a useful expression is ID.value.length == 0. Note that ID.length is not a valid expression. Also since a checkbox control is an array it is not a valid expression to write ID[0].value == . Because if at option in the checkbox control is unchecked, it's value will not be an empty string. It will simply not exist in the array.

Initial Control State

Every control in your form has an initial default property states for the visible, expanded, value, valid & enabled properties. However you can change a controls initial state in frevvo’s form designer Edit tab. A control’s initial state can be modified several ways. One way is by simply tying a value into an input control. This sets the default value for the control when the form is first opened in use mode. Another way is by expanding or collapsing group controls. This sets the initial expanded state. The default state for the visible and enabled properties is set via the controls edit property panel. The edit property contains checkboxes for visible and enabled for controls on which those properties make sense like input controls.

Dynamic Content

Real business forms often require dynamic content in dropdown list. Often based on the value entered into one form field, the values in other fields or options available in select controls need to be dynamic.

Rules allow invocation of http gets that return X-JSON headers with JSON objects. This allows complete flexibility in assignment of default values populated into form fields such as text controls and select (radios, dropdown, checkbox) controls. You can also use http.post(), http.delete(), and http.put() in rules, although you must use URL parameters with them, as they do not all support payloads.

Here is an example that shows the syntax of the http.get. This rule invokes the http get which must return a JSON object. The method on the servlet can do whatever necessary such as querying a database given the itemName to retrieve the itemPrice. In this example the JSON object returned contains a field called price. The eval converts and assigns the JSON object to the javascript variable x. Then x can be used in the rule as necessary. In this case it is used to set a value to the form field called Price.

eval('x=' + http.get('http://<webhost>/test/json/getPrice?itemName=' + itemName.value)); 
Price.value = x.price;

Imagine another example where the JSON object returned in the http.get response contains an array called clients. This array can then be used to set the options in a dropdown list.

eval('x=' + http.get('http://<webhost>/test/json/getClients')); 
Clients.options = x.clients;

Here is another example of a servlet that returns a JSON object after authenticating a user/password.

@Override
public void doGet (HttpServletRequest request, HttpServletResponse response)
	throws ServletException, IOException
{		
  try {
	String u = request.getParameter("username");
	String p = request.getParameter("password");

        if (authenticate(u, p) == null)
		response.addHeader("X-JSON", "{auth:false}");
	else
		response.addHeader("X-JSON", "{auth:true}");
  } catch (Exception e) {
	throw new ServletException(e);
  }
}

This servlet could be used in a rule as follows:

if (signForm.clicked) 
{
  eval('x=' + http.get('http://<webhost>/MYservices/signForm?username=' + u.value + '&password=' + p.value));
 
  if (x.auth) 
  {
    m.value = "<center>Authenticationn Succeeded</center>";
  } else 
  {
    m.value = "<center>Invalid username or password</center>";
    }
}

It is important to note that the http.get is accessing your http service via a URL. Certain characters must be encoded in order to correctly pass thru via an HTTP URL. [| W3 Schools] provides one good reference on this topic. You may not always be able to control the values your users enters into your form fields. If the value may contain one of these characters that value must be encoded.

For example, this http.get contains a password parameter. Since user passwords may contain characters such as '#' you should encode the value. The built-in javascript method encodeURIComponent() makes this easy.

eval('x=' + http.get('http://<webhost>/MYservices/signForm?username=' + 
                          u.value + '&password=' + encodeURIComponent(p.value)));

You may also need to decode the URL parameter in your HTTP service. For example:

import java.net.URLDecoder; 

String p = request.getParameter("password"); 
p = URLDecoder.decode(password, "UTF-8"); 

For complete details of integration with your backend systems to provide dynamic data into your forms, see the section on integration.

Reusing Dynamic Content

Fetching dynamic content from you backend system can be the source of degrading form performance. If your form needs to use the dynamic content multiple times you can improve performance by fetching the content once from the http.get() and saving the returned JSON string in a hidden text form control. Then you can later read the text control value and eval it again rather than having to call your backend system multiple times.

For example add a hidden text control to your form named jsonUserData. Add a single line to the rule that retrieves the user Data from your backend system via the http.get():

  jsonUserDate.value = x;

In other rules that also need the user data, rather than calling http.get() to your backend system again, add the following line to your rule:

  var val = jsonUserDate.value; 
  eval('x' = val);

This will have the affect of setting x to the same string as if you had again fetched content from your backend system.

Relative URIs

The dynamic content described above requires an http get to a specific URI service returning a JSON object. The examples above specified absolute URI paths. You can also use a relative path.

Assuming the frevvo Form Server is running on http://www.myhost.com, http.get(‘http://www.myhost.com/path/to/resource’) may instead be written as http.get(‘/path/to/resource’).

For example:

eval('x=' + http.get('http://<webhost>/database/mydb/getPrices')); 

In this example the path to the URI service is an absolute hard coded path. When the service is running on the same host as the frevvo form server you may use a relative URI. One common scenario where this is applicable is for Live Forms In-house customers who have also installed the frevvo database connector. In this case the rule is best written as follows because it becomes portable if you move your form server from one <webhost> to another <webhost> as is common when running under development servers and moving to production servers.

eval('x=' + http.get('/database/mydb/getPrices')); 

Templatized URIs

The URIs used in a http get very often contain variables. For example, the service getPrice takes as an argument an item name:

eval('x=' + http.get('http://<webhost>/test/json/getPrice?itemName=' + itemName.value)); 
Price.value = x.price;

This URI can also be shortened using a simplified template syntax:

eval('x=' + http.get('http://<webhost>/test/json/getPrice?itemName={itemName}')); 
Price.value = x.price;

For example assuming that when the form is used the field named itemName contains the value 'laptop', then using examples of both absolute and relative URIs and assuming that the service is running on http://www.frevvo.com:

http.get('/path/to/service/{itemName}') 
   => 'http://www.frevvo.com/path/to/service/laptop'

http.get('http://www.frevvo.com/path/to/service/{itemName}') 
   => 'http://www.frevvo.com/path/to/service/laptop'

Note that since templates need not be bound to form controls the value for 'itemName' may be passed into the form using _data rather than as a value entered into the field by the user. If instead you use the syntax itemName.value in your URI then a control named itemName must exist as a field in your form.

This can be a very good way to dynamically configure your service's location rather than hard-coding the location into the rule. This form was loaded with the Url parameter &_data(myBaseUrl:'http://www.myhost.com')

http.get('{myBaseUrl}/path/to/service') => 'http://www.myhost.com/path/to/service

In this case since we do not want a form field to display myBaseUrl we use a template rather then adding a special field just for the purposes of passing the base Url into the rule.

Url Parameters Accessed in Rules

Url parameters passed into your form via the _data frevvo parameter can be accessed in rules several ways. If &_data(FirstName:'Joe') was added to your form Url, then:

  1. FirstName.value - only for parameters bound to a control in your form
  2. {FirstName} - only for parameter used in http get templatized URI
  3. _data.getParameter('FirstName') - if used anywhere else in a rule other than a URI.

Option 2 & 3 are available for both bound and unbound controls. So choose whichever approach is the simplest for you.

Built-in Data

frevvo makes certain data available to your rules. This includes information about the person currently using your form, the tenant and form information. You retrieve this data in your rule using the _data.getParameter('<data name>') syntax. Here is the list of available data:

  • tn.id - Tenant ID
  • tn.name - Tenant Name
  • subject.id - logged in user's username.
  • subject.first.name - Logged in users's First Name
  • subject.first.name - Logged in users's Last Name
  • subject.email - Logged in users's email address
  • subject.roles - A list of all the roles for the logged in user (available in v4.1.5)
  • subject.reports.to - Logged in users's Reports To
  • user.id - Owner of form/flow and user folder name in the filesystem
  • user.name - TBD

The following data is available in v4.1.4 and later releases.

  • app.id - The unique id associated with a given application. See Sharing Forms
  • app.name - The name of the application
  • form.type.id - The unique id associated with a given form. See Sharing Forms
  • flow.type.id - The unique id associated with a given flow. See Sharing Forms
  • form.id - The unique form instance id. This id is unique for each for submission.
  • flow.id - The unique flow instance id. This id is unique for each flow submission.
  • flow.activity.id - The Id of the current workflow activity
  • flow.activity.name - The name of the current workflow activity
  • form.extid - Client defined extId passed in the formtype Url parameter.
  • flow.extid - Client defined extId passed in the flowtype Url parameter

Security Subject Information

You can use a form.load rule to pre-populate fields in your form with information about the currently logged in user. For example, if you have controls in your form named Id, FirstName, LastName, Email and Roles, the following rule will prefill those fields as indicated below.

if (form.load) {
  // User Information
  Id.value = _data.getParameter('subject.id'); // Username
  FirstName.value = _data.getParameter('subject.first.name');
  LastName.value = _data.getParameter('subject.last.name');
  Email.value = _data.getParameter('subject.email');
  
  var roles = _data.getParameter ("subject.roles");
  if (roles) {
    eval ('x=' + roles);
    Roles.options = x;
  }
}

This rule is useful in a workflow where you want to make a the tab named Review visible only for the workflow activity named Manager Review.

if (form.load) {
  if (_data.getParameter('flow.activity.name') == 'Manager Review') {
    Review.visible = true;
  }
}

Common Methods (includes.js)

This feature is mainly intended for OEM frevvo partners. Often there are common rule code that is reused over and over in many forms. Traditionally this code must be duplicated in each form. Live Forms is now packaged with a file in frevvo.war /WEB-INF/rules/includes.js which is initially empty. OEM frevvo partners can put commons functions into includes.js. There is a second file com.frevvo.forms.model/src/main/resources/com/gauss/forms/rule/executor/includes.js also packaged in frevvo.war whose contents are defined by frevvo.

When you write any form rule you can now call functions defined in these two includes.js files above. The first one is for OEM partners to create and repackage with frevvo.zip. The second one is frevvo's and is automatically updated when there is a new release and should not be modified by OEM partners.

Extracting common functions into includes.js can simplify rules by calling a common method in includes.js rather than coping the common code into each rule.

Note that includes.js is parsed and compiled once when frevvo starts. If you update this file with new functions and fixes to existing functions you must restart frevvo for the changes to take affect.

Migration Issues

Options

When upgrading frevvo Live Forms versions v3.3 and older, any rules written using string comparison against <control>.options[x] will need to be re-written. In prior versions the options[] array contains only the label string. The options[] array contains both the option label and the option value in the syntax <value>=<label>. Rules written in v3.3 and prior may fail unless they are written to take this change into account.

Here is an example where RGB is the name of a radio control with options: R=red, G=blue, B=green. This rule triggers each time the user selects a new options. It finds the value and label of the selected option.

if (RGB.value.length > 0) {
  for (x in RGB.options) {

    var opt = RGB.options[x];
    var val= opt.split('=')[0];
    var lab= opt.split('=')[1];

    if (RGB.value == val) {
      V.value = val;
      L.value = lab;
    }
  }
}

Refer to the select control options documentation for more information.


Special Cases

Why do I need a local variable for certain cases ?

There are rules scenarios where you can't use a frevvo control directly in a rule expression and you are forced to define a local variable, perform the computation using the local variable and assign the value to the control at the conclusion of the computation.

For instance, assume a form that calculates a total from a list of subtotals. The total is a control T and subtotals are represented as a repeat of controls S. In other words, T holds the total of adding all values in S. You could write the rules as:

T.value = 0;
for (var i = 0; i < S.value.length; i++) {
  T.value = T.value + S[i].value;
}

The code above makes logical sense but it just won't work. In a nutshell this particularity of the frevvo implementation can be resumed this way:

The right hand side of an assignment expression resolves to the value of a frevvo control passed to a rule when it is invoked. The left hand side uses a reference to the control.

Lets work with a concrete example to understand the concept. Assume that there are two subtotals in the form, 12 and 14 and the total is correctly set to 26. Now, you add 50 as a third subtotal and the rule fires as a consequence. The values of the controls involved in the rule are passed as parameters to the rule: the subtotals 12,14 and 50 and the current total (value of T), 26. The core of the matter is in the expression:

 T.value = T.value + S[i].value;


The expression will be evaluated three times (since there are three subtotals) but for every iteration, the T.value operand on the right hand side will always evaluate to 26 which is not the desired behavior and will lead to an incorrect result. Again, this happens because the right hand side of that expression is resolved based on the values initially passed to the rule as parameters.

Frevvo explicitly imposes this restriction for the sake of efficiency and there would be a significant impact in performance if the restriction was not in place. Lets rewrite the rule using a local variable:

var tot = 0;
for (var i = 0; i < S.value.length; i++) {
  tot = tot + S[i].value;
}
T.value = tot;


This rule will produce the expected result.

FAQ

Why does my rule not execute?

A rule will not execute when circular logic is detected. Currently circular dependencies are not permitted. This example tries to set the value of the same control used to trigger the rules execution. This is not permitted and this rule will not execute. This restriction may be lifted in a future release.

if (color.value == 'red') {
  color.value = 'blue';
}

No execution error will be logged in frevvo server log files (see rule debugging above). The rule will simply not be executed.

Personal tools