Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Table of Contents
maxLevel12

Calculate a Total

You have a form with three controls and you have assigned them Names N1, N2 and T respectively. When the user enters a value in either N1 or N2 you want to set the value of T to the sum of N1 and N2. The rule would be written as

Code Block
languagejavascript
themeConfluence
languagejavascript
T.value = N1.value + N2.value;

...

Code Block
if (form.load) {
  var an = _data.getParameter ("flow.activity.name");
  if (an === 'Manager' || an === 'VP'){
    ManagerApproval.visible = true;
  } else {
    ManagerApproval.visible = false;
  }
}

...

Let's say you have calculated a sum in a Number control in your form and you want to display it in a Message control and format it as a money value with commas and decimal places.  You will need a Number control named Num and a message control named Message in your form. This rule will display the number entered in the number control with commas. If the user enters 5600.44 in the number field then the result in the message control would look like this:"5,600.44".

 

 

 

 

Textarea Max Length

In html there is no way to set a maxLength on a textarea control. This is why the textarea control does not have a maxlength property like the text control does. It is possible to do this via a business rule. This example form has a textarea control named 'Desc' where the user can enter up to a 500 character description. On this control we also set the ErrorMsg property to the string 'You must limit your description to 500 characters'. This message is automatically displayed when the description control is set to invalid by the following business rule.

...

Code Block
var x, x1, x2;
if (Num.value > 0) {
  Desc.valid = false  var nStr = Num.value.toFixed(2);
    nStr += '';
 } else { x = Desc.validnStr.split('.');
    x1 = true;x[0];
    } 

You can even customize the error message by adding this line to your rule. Now the error message will tell the user how many characters they are over the maximum allowed.

Code Block
Desc.status = 'Invalid. Max 20 chars allowed and you have ' + Desc.value.length; 

Textarea newline vs break

Users typically enter multi-line text into textarea controls. If you want to display that text in an html context, for example on a web page or in an html formatted email or in your form's Form Action display message you will need to replace newlines with html breaks. This caused by the fact that line breaks entered into a web form textarea are represented by a single newline character \n while line breaks in an html context are represented by the html break characters.

Our example has a textarea control named Description and a hidden control named DF. The user types into the visible control named Description and a business rules converts the newline characters \n into html breaks.

Code Block
var x = Description.value; 
x = x.replace(/\\r/g,"");
x = x.replace(/\\n/g,"<br/>");
DF.value = x; 

Dropdown Options

This example automatically sets the option selected in one dropdown based on the option selected in another. This is often useful when you have a form with choices that were dynamically populated. For example, imagine product choices which are descriptive text. When the user selects a product, your form needs to perform an action based on a product ID rather than the descriptive product text. A nice way to do this is to have the rule that dynamically populates the product choices dropdown also populate a product ID dropdown which remains an invisible control in the form. The product choices dropdown control was named Products and the product ID dropdown control was named PID

The 1st rule "Load Products" populates both the visible and hidden dropdowns with options from a database.

Code Block
/*member description productId resultSet */
var x;
 
if (form.load) { 
eval('x=' + http.get('http://localhost:8082/database/products'));   
 
    var opts1 = []; 
    var opts2 = []; 
 
    for (var i=0; i < x.resultSet.length; i++) { 
        if (x.resultSet[i]) { 
            opts1[i] = x.resultSet[i].description; 
            opts2[i] = x.resultSet[i].productId; 
    } 
} 
 
 
Products.options = opts1; 
PID.options = opts2; 
Products.value = opts1[0]; // default to 1st product option 
PID.value = opts2[0]; 
}

Finding a Selected Options Index

The 2nd rule Select Product ID keeps the hidden PID dropdown syncronized with the visible Products dropdown.

Code Block
if (Products.value.length > 0) 
{ 
    var i; 
    for (var x in Products.options) {
        if (Products.value === Products.options[x])x2 = x.length > 1 ? '.' + x[1] : '';
    var rgx = /(\d+)(\d{3})/;
    while (rgx.test(x1)) {
 x1 = x1.replace(rgx, '$1' + ',' + '$2');
    }
    Message.value = x1 + x2;
}

Textarea Max Length

In html there is no way to set a maxLength on a textarea control. This is why the textarea control does not have a maxlength property like the text control does. It is possible to do this via a business rule. This example form has a textarea control named 'Desc' where the user can enter up to a 500 character description. On this control we also set the ErrorMsg property to the string 'You must limit your description to 500 characters'. This message is automatically displayed when the description control is set to invalid by the following business rule.

Code Block
if (Desc.value.length > 500) {
  Desc.valid = false; 
} else {
  Desc.valid = true; 
} 

You can even customize the error message by adding this line to your rule. Now the error message will tell the user how many characters they are over the maximum allowed.

Code Block
Desc.status = 'Invalid. Max 20 chars allowed and you have ' + Desc.value.length; 

Textarea newline vs break

Users typically enter multi-line text into textarea controls. If you want to display that text in an html context, for example on a web page or in an html formatted email or in your form's Form Action display message you will need to replace newlines with html breaks. This caused by the fact that line breaks entered into a web form textarea are represented by a single newline character \n while line breaks in an html context are represented by the html break characters.

Our example has a textarea control named Description and a hidden control named DF. The user types into the visible control named Description and a business rules converts the newline characters \n into html breaks.

Code Block
var x = Description.value; 
x = x.replace(/\\r/g,"");
x = x.replace(/\\n/g,"<br/>");
DF.value = x; 

Dropdown Options

This example automatically sets the option selected in one dropdown based on the option selected in another. This is often useful when you have a form with choices that were dynamically populated. For example, imagine product choices which are descriptive text. When the user selects a product, your form needs to perform an action based on a product ID rather than the descriptive product text. A nice way to do this is to have the rule that dynamically populates the product choices dropdown also populate a product ID dropdown which remains an invisible control in the form. The product choices dropdown control was named Products and the product ID dropdown control was named PID

The 1st rule "Load Products" populates both the visible and hidden dropdowns with options from a database.

Code Block
/*member productCode, productName, resultSet*/
var x;
  
if (form.load) {
  eval('x=' + http.get('https://app.frevvo.com/database/BIRT/allProducts'));  
 
    var opts1    i = Products.options.indexOf(Products.options[x]);
  }  PID.valuevar opts2 = PID.options[i] + ''; 
}

In v4 rules using hidden dropdowns to keep descriptive option labels visible to the user while keeping cryptic database values hidden are often no longer necessary. Dropdown options have values distinct from the human visible option labels. The above can now be achieved with a single simpler rule:

Code Block
/*member description productId
resultSet */
var x, opts1;   for (var i=0; i < x.resultSet.length; i++) {
        if (x.resultSet[i]) {
             opts1[i] = x.resultSet[i].productId+ '=' + xproductName;
            opts2[i] = x.resultSet[i].descriptionproductCode;
        }
    }
 
  RdocnumProducts.options = opts1; 

Here is another rule that dynamically populates both the product choices and product ID dropdowns. This rule calls a REST Service which returns an object rather than the resultset returned by the database connector as shown above. See the section on dynamic content for more details.

Code Block
/*member
ids products */
var xPID.options = opts2;
  if (SProducts.value.length >= 0) {
    eval('x=' + http.get('http://localhost:8182/products/?category=' + S.value)); 
    P.options = x.products; 
    ID.options = x.ids; 
} 

Synchronized Selects

The Product Search example above is often used in conjunction with a hidden select control. Imagine that your database table contains a list of products. Each product has product description also a unique product ID. The user needs to select a product from a dropdown on your form. You want to populate the dropdown with the product descriptions. The users do not need to see or know the product IDs but you need to use the ID as the key into the database for other selects. To do this add another hidden dropdown to the form and populate it with the IDs. This example has a visible dropdown name Products and an invisible dropdown named PID. See the rule above that populates these dropdowns dynamically from the database.

This rule below keeps the PID selected option in sync with the selected Product.

Code Block
var i, x; 
for (x in Products.options) { 
// Determine the index of the selected product in the Products dropdown options 
if (Products.value === Products.options[x]) 
    i = Products.options.indexOf(Products.options[x]); 
}

 
// Changed the selected PID to match the selected Product 
PID.value = PID.options[i] + '';

Clearing Dropdown Options

This sample resets a dropdown option to the automatically added blank option. For dropdowns added from palette controls and from schema, 

Frevvoproduct
automatically adds a blank option so the dropdown initially shows no choice by default. To reset the dropdown, set the dropdown control's value to null not the empty string. The empty string will not work since the empty string is not a valid option. This form resets the dropdown named size whenever the value of the product option changes.

Code Block
if (productopts1[0]; // default to 1st product option
  PID.value = opts2[0];
}

Finding a Selected Options Index

The 2nd rule Select Product ID keeps the hidden PID dropdown synchronized with the visible Products dropdown.

Code Block
}
if (Products.value.length > 0)
{
    var i;
    for (var x in Products.options) {
        if ((Products.value + '=' + Products.value) === Products.options[x]){
            i = Products.options.indexOf(Products.options[x]);
        }
    }
 
  PID.value = PID.options[i].split('=')[0];
}

In v4 rules using hidden dropdowns to keep descriptive option labels visible to the user while keeping cryptic database values hidden are often no longer necessary. Dropdown options have values distinct from the human visible option labels. The above can now be achieved with a single simpler rule:

Code Block
/*member description productId resultSet */
var x, opts1;
 
for (var i=0; i < x.resultSet.length; i++) { 
    if (x.resultSet[i]) { 
            opts1[i] = x.resultSet[i].productId+ '=' + x.resultSet[i].description; 
    } 
} 
Rdocnum.options = opts1; 

Here is another rule that dynamically populates both the product choices and product ID dropdowns. This rule calls a REST Service which returns an object rather than the resultset returned by the database connector as shown above. See the section on dynamic content for more details.

Code Block
/*member ids products */
var x;
 
if (S.value.length > 0) {
    eval('x='  size.value = null; 
} 

Default Option

When your options are set dynamically as shown below in a business rule, you cannot set a default in on the form designer. You need to set the default in the rule. If your options have <value>=<label> where value is different from label, make sure you set the <control>.value to <value> not <label> and not <value>=<label>

Code Block
if (form.load) { 
    var cc = ['R=Red', 'B=Blue', 'G=Green'];
    Colors.options = cc;
    Colors.value = 'B';
}

Populating Dropdown Options from a Google Sheet

Dropdown control options can be dynamically populated from a Google Sheet using a business rule. Here is an example of a rule that populates a dropdown control named Colors with color options from a Google Sheet.

...

  • Create a Form with a control called Colors.
  • Use this rule to populate the dropdown options with the colors Red, Blue, Green and Orange.
Code Block
/*member colors, results */
var x;

if (form.load) {
    var readquery = '/google/spreadsheets/query/u/<google username>/p/<google pswd>/s/ColorList/w/Sheet1?media=json';
    eval('x=' + http.get(readquery));

    var opts = [''];
    if (x.results) {
        for (var i = 0; i < x.results.length; i++) {
            if (x.results[i].colors) {
                opts[i + 1] = x.results[i].colors;
            }
        }
    }
    Colors.options = opts;    //Colors is the name of my dropdown control
}

Image Removed 

Refer to this documentation for more information about

Frevvoproduct
 and the Google Connector

Checkbox Options - Assigning Color to Checkbox Choices

Checkbox controls are different from all other 

Frevvoproduct
palette controls in that they are multi-select. Therefore the way to write rules with checkbox controls are in many ways similar to rules with repeat controls. This rule has a checkbox controls with name colorPalette with the options: purple, green, blue, yellow, orange. The form also contains a text control with name colorChoice. This rule assigns colorChoice the choices selected from colorPalette.

Code Block
var choices = ''; 
for (var i = 0; i < colorPalette.value.length; i++) 
{  
    choices = choices + colorPalette[i].value; 
} 
colorChoice.value = choices; 

Notice that similar to repeat controls, due to an internal evaluation limitation, you must collect the choices in a variable inside the for loop. And then assign that control Name.value to that variable outside the for loop.

This rule is another example showing how checkbox controls are array types.

Code Block
if (colorPalette.value.length > 0) 
{ 
    colorChoice.value = 'Thank you for choosing colors'; 
} 
else 
{ 
    colorChoice.value = 'Please choose colors...'; 
} 

Checkbox Options - Making a Control Visible/Invisible Based on Checkbox Choices

This rule makes visible/invisible a control based on which checkbox options a user selects. This form contains a multi select checkbox named Structures. If the user selects the option "Detached Garage" or "House", we want to make visible a text field named Details.

Again since a checkbox is multi select, it is handled as an array. The array will contain all selected (checked) options.

It is important to note that when a checkbox is added to the form from the palette and its options are multiple words containing spaces, the option array has converted each space character to the '_' character. We must make the comparison as shown below. Checkbox controls from schema do not have space replaced with '_'.

Code Block
var found = false; 
for (var i = 0; i < Structures.value+ http.get('http://localhost:8182/products/?category=' + S.value)); 
    P.options = x.products; 
    ID.options = x.ids; 
} 

Synchronized Selects

The Product Search example above is often used in conjunction with a hidden select control. Imagine that your database table contains a list of products. Each product has product description also a unique product ID. The user needs to select a product from a dropdown on your form. You want to populate the dropdown with the product descriptions. The users do not need to see or know the product IDs but you need to use the ID as the key into the database for other selects. To do this add another hidden dropdown to the form and populate it with the IDs. This example has a visible dropdown name Products and an invisible dropdown named PID. See the rule above that populates these dropdowns dynamically from the database.

This rule below keeps the PID selected option in sync with the selected Product.

Code Block
var i, x; 
for (x in Products.options) { 
// Determine the index of the selected product in the Products dropdown options 
if (Products.value === Products.options[x]) 
    i = Products.options.indexOf(Products.options[x]); 
}

 
// Changed the selected PID to match the selected Product 
PID.value = PID.options[i] + '';

Clearing Dropdown Options

This sample resets a dropdown option to the automatically added blank option. For dropdowns added from palette controls and from schema, 

Frevvoproduct
automatically adds a blank option so the dropdown initially shows no choice by default. To reset the dropdown, set the dropdown control's value to null not the empty string. The empty string will not work since the empty string is not a valid option. This form resets the dropdown named size whenever the value of the product option changes.

Code Block
if (product.value.length > 0) {  
    size.value = null; 
} 

Default Option

When your options are set dynamically as shown below in a business rule, you cannot set a default in on the form designer. You need to set the default in the rule. If your options have <value>=<label> where value is different from label, make sure you set the <control>.value to <value> not <label> and not <value>=<label>

Code Block
if (form.load) { 
    var cc = ['R=Red', 'B=Blue', 'G=Green'];
    Colors.options = cc;
    Colors.value = 'B';
}

Populating Dropdown Options from a Google Sheet

Dropdown control options can be dynamically populated from a Google Sheet using a business rule. Here is an example of a rule that populates a dropdown control named Colors with color options from a Google Sheet.

  • Create a Google Sheet with a column named Colors containing a list of colors.

     
     Image Added
  • Create a Form with a control called Colors.
  • Use this rule to populate the dropdown options with the colors Red, Blue, Green and Orange.
Code Block
/*member colors, results */
var x;

if (form.load) {
    var readquery = '/google/spreadsheets/query/u/<google username>/p/<google pswd>/s/ColorList/w/Sheet1?media=json';
    eval('x=' + http.get(readquery));

    var opts = [''];
    if (x.results) {
        for (var i = 0; i < x.results.length; i++) 

...

{
     

...

 

...

 

...

 

...

 

...

   

...

if (x.results[i].

...

colors) {
          

...

 

...

 

...

    opts[i + 1] 

...

= x.results[i].colors;
     

...

  

...

  

...

 

...

 

...

 

...

}

...

      

...

 

...

 

...

}
 

...

 

...

 

...

 }
    

...

Colors.

...

options = 

...

opts;    //Colors is the name 

...

of 

...

my 

...

dropdown control
}

...

Note that when we hide Details we also clear its value. This is because the user may have selected one of the Structures checkboxes that made Details visible AND entered a value into Details. And then they may have changed their minds and uncheck the option that caused Details to become visible. If you don't want the value entered into Details to be in your form submission, clear the value when hiding it.

Many Checkbox Comments

This rule makes an associated comment input control visible and required when a checkbox is checked. The for loop determines which checkboxes are checked and sets an appropriately named variable to true. Depending on the value of checkbox the associated input control will be made visible and required via the if/else and will be hidden and not-required when it is un-checked again. This is a very common rule design pattern.

You can style this form so the comment input controls align with the checkbox options. See details and download a working sample form here

...

Image Added 

Refer to this documentation for more information about

Frevvoproduct
 and the Google Connector

Checkbox Options - Assigning Color to Checkbox Choices

Checkbox controls are different from all other 

Frevvoproduct
palette controls in that they are multi-select. Therefore the way to write rules with checkbox controls are in many ways similar to rules with repeat controls. This rule has a checkbox controls with name colorPalette with the options: purple, green, blue, yellow, orange. The form also contains a text control with name colorChoice. This rule assigns colorChoice the choices selected from colorPalette.

Code Block
var choices = ''; 
for (var i = 0; i < MedicalIssuescolorPalette.value.length; i++) 
{  
    choices = choices if+ (MedicalIssuescolorPalette[i].value; === 'heart_problem') {
    heartProblem = true;
  } else if (MedicalIssues[i].value === 'food_allergy') 
} 
colorChoice.value = choices; 

Notice that similar to repeat controls, due to an internal evaluation limitation, you must collect the choices in a variable inside the for loop. And then assign that control Name.value to that variable outside the for loop.

This rule is another example showing how checkbox controls are array types.

Code Block
if (colorPalette.value.length > 0) 
{ 
   foodAllergy = true;
  } else if (MedicalIssues[i] colorChoice.value === 'rashes') {
Thank you for choosing colors'; 
} 
rasheselse =
true;{ 
 } else if (MedicalIssues[i]colorChoice.value === 'joint_injury') {
    jointInjury = true;
  } else if (MedicalIssues[i].value === 'asthma') {
    asthma = true;
  } else if (MedicalIssues[i].value === 'moodiness'Please choose colors...'; 
} 

Checkbox Options - Making a Control Visible/Invisible Based on Checkbox Choices

This rule makes visible/invisible a control based on which checkbox options a user selects. This form contains a multi select checkbox named Structures. If the user selects the option "Detached Garage" or "House", we want to make visible a text field named Details.

Again since a checkbox is multi select, it is handled as an array. The array will contain all selected (checked) options.

It is important to note that when a checkbox is added to the form from the palette and its options are multiple words containing spaces, the option array has converted each space character to the '_' character. We must make the comparison as shown below. Checkbox controls from schema do not have space replaced with '_'.

Code Block
var found = false; 
for (var i = 0; i < Structures.value.length; i++) 
{ 
    if (Structures[i].value === 'Detached_Garage' || 
        Structures[i].value === 'House') { 
      found = true; 
      break; 
    } 
} 
if (found === true) { 
    Details.visible = true; 
} else { 
    Details.visible = false; 
    Details.value = null; 
} 

Note that when we hide Details we also clear its value. This is because the user may have selected one of the Structures checkboxes that made Details visible AND entered a value into Details. And then they may have changed their minds and uncheck the option that caused Details to become visible. If you don't want the value entered into Details to be in your form submission, clear the value when hiding it.

Many Checkbox Comments

This rule makes an associated comment input control visible and required when a checkbox is checked. The for loop determines which checkboxes are checked and sets an appropriately named variable to true. Depending on the value of checkbox the associated input control will be made visible and required via the if/else and will be hidden and not-required when it is un-checked again. This is a very common rule design pattern.

You can style this form so the comment input controls align with the checkbox options. See details and download a working sample form here

Code Block
var heartProblem = false;
var foodAllergy = false;
var rashes = false;
var jointInjury = false;
var asthma = false;
var moodiness = false;

for (var i = 0; i < MedicalIssues.value.length; i++)
{
  if (MedicalIssues[i].value === 'heart_problem') {
    heartProblem = true;
  } else if (MedicalIssues[i].value === 'food_allergy') {
    foodAllergy = true;
  } else if (MedicalIssues[i].value === 'rashes') {
    rashes = true;
  } else if (MedicalIssues[i].value === 'joint_injury') {
    jointInjury = true;
  } else if (MedicalIssues[i].value === 'asthma') {
    asthma = true;
  } else if (MedicalIssues[i].value === 'moodiness') {
    moodiness = true;
  }
}

if (heartProblem === true) {
  heartProblemDetails.visible = true;
  heartProblemDetails.required = true;
} else {
  heartProblemDetails.visible = false;
  heartProblemDetails.required = false;
  //heartProblemDetails.value = null;
}

if (foodAllergy === true) {
  foodAllergyDetails.visible = true;
  foodAllergyDetails.required = true;
} else {
  foodAllergyDetails.visible = false;
  foodAllergyDetails.required = false;
  //foodAllergyDetails.value = null;
}

if (rashes === true) {
  rashesDetails.visible = true;
  rashesDetails.required = true;
} else {
  rashesDetails.visible = false;
  rashesDetails.required = false;
  //rashesDetails.value = null;
}

if (jointInjury === true) {
  jointInjuryDetails.visible = true;
  jointInjuryDetails.required = true;
} else {
  jointInjuryDetails.visible = false;
  jointInjuryDetails.required = false;
  //jointInjuryDetails.value = null;
}

if (asthma === true) {
  asthmaDetails.visible = true;
  asthmaDetails.required = true;
} else {
  asthmaDetails.visible = false;
  asthmaDetails.required = false;
  //asthmaDetails.value = null;
}

if (moodiness === true) {
  moodinessDetails.visible = true;
  moodinessDetails.required = true;
} else {
  moodinessDetails.visible = false;
  moodinessDetails.required = false;
  //moodinessDetails.value = null;
}

Checkbox Initialization

Since checkbox options are multi-select, in order to select multiple options via a rule you must use this syntax. The correct way to initialize the checkbox control value is to collect all required options in an array and then assign that array as the value of your checkbox control.  In this example CB is the name of a checkbox controls with the following options: red, green, blue. This rule selects all of the options.

Code Block
CB.value = ['red', 'green', 'blue']; 

To clear all checked options in the control named CB:

Code Block
CB.value = []; 

Displaying Selected Checkbox Labels

In this example, the rule displays the labels of the checkboxes the user selects.

Code Block
var x;
var selectedcolors = '';

for (var i = 0; i < RGB.value.length; i++) 
{ 
    var v = RGB[i].value; 
    for (x in RGB.options) {

   moodiness = true;   }var }opt 
if (heartProblem === true) {= RGB.options[x]; 
     heartProblemDetails.visible = true; var val= heartProblemDetails.required = true;
} else {opt.split('=')[0]; 
     heartProblemDetails.visible = false; var lab= heartProblemDetails.required = false;opt.split('=')[1];
   //heartProblemDetails.value = null; }  if (foodAllergyv === trueval) { 
     foodAllergyDetails.visible   = true;   foodAllergyDetails.requiredselectedcolors = true;
} else { selectedcolors + ' ' + lab; 
 foodAllergyDetails.visible = false;   foodAllergyDetails.required = false;} 
 //foodAllergyDetails.value = null; } 
if (rashes}

Image Added

T/F Boolean

T/F controls are simplified checkbox controls with only a single visible option. This rule makes the control named "s" visible if the T/F control named "agree" is checked and invisible if the T/F control named "agree" is unchecked.

Code Block
if (agree[0].value === 'true') {
  rashesDetailss.visible = true;
  rashesDetails.required = true;
} else {
  rashesDetailss.visible = false;
  rashesDetails.required = false;
  //rashesDetails.value = null;
}

if (jointInjury === true) {
  jointInjuryDetails.visible = true;
  jointInjuryDetails.required = true;
} else {
  jointInjuryDetails.visible = false;
  jointInjuryDetails.required = false;
  //jointInjuryDetails.value = null;
}

if (asthma === true) {
  asthmaDetails.visible = true;
  asthmaDetails.required = true;
} else {
  asthmaDetails.visible = false;
  asthmaDetails.required = false;
  //asthmaDetails.value = null;
}

if (moodiness === true) {
  moodinessDetails.visible = true;
  moodinessDetails.required = true;
} else {
  moodinessDetails.visible = false;
  moodinessDetails.required = false;
  //moodinessDetails.value = null;
}

Checkbox Initialization

Since checkbox options are multi-select, in order to select multiple options via a rule you must use this syntax. The correct way to initialize the checkbox control value is to collect all required options in an array and then assign that array as the value of your checkbox control.  In this example CB is the name of a checkbox controls with the following options: red, green, blue. This rule selects all of the options.

Code Block
CB.value = ['red', 'green', 'blue']; 

To clear all checked options in the control named CB:

Code Block
CB.value = []; 

Displaying Selected Checkbox Labels

In this example, the rule displays the labels of the checkboxes the user selects.

Code Block
var x;
var selectedcolors = '';

for (var i = 0; i < RGB.value.length; i++) 
{ 
    var v = RGB[i].value; 
    for (x in RGB.options) {

        var opt = RGB.options[x]; 
        var val= opt.split('=')[0]; 
        var lab= opt.split('=')[1];
        if (v === val) { 
            selectedcolors = selectedcolors + ' ' + lab; 
        } 
    } 
}

Image Removed

T/F Boolean

T/F controls are simplified checkbox controls with only a single visible option. To test if the T/F control named agree is checked and make the control s visible if checked and make s invisible if not checked.

Code Block
if (agree[0].value === 'true') {
  s.visible = true;
} else {
  s.visible = false;
}

To clear a checkmark from a T/F control you must set the value to null and ensure that the control is not required as follows:

Code Block
agree.required = false;
agree.value = null;

Repeating Checkboxes

Checkboxes inside repeat controls must be treated as an array (each checkbox control's values) of checkbox option values which is inside another array (the repeating checkbox control itself). This form example has a repeating section containing two controls -- Message which is a text control and AreYouAttending which is a checkbox control with a single option 'yes'. To access the selected options the syntax is:

AreYouAttending[i].value[0] === 'yes'

Code Block
}

To clear a checkmark from a T/F control you must set the value to null and ensure that the control is not required as follows:

Code Block
agree.required = false;
agree.value = null;

Repeating Checkboxes

Checkboxes inside repeat controls must be treated as an array (each checkbox control's values) of checkbox option values which is inside another array (the repeating checkbox control itself). This form example has a repeating section containing two controls -- Message which is a text control and AreYouAttending which is a checkbox control with a single option 'yes'. To access the selected options the syntax is:

AreYouAttending[i].value[0] === 'yes'

Code Block
for (var i = 0; i < AreYouAttending.value.length; i++) 
{ 
    if (AreYouAttending[i].value[0] === 'yes') {
        Message[i].value = Name.value + 
               ' is attending event #' + i; 
    } 
} 

String Concatenation

Message controls can be used in business rules to create summary information on your form from values entered into earlier form fields. This rule uses javascript variables to concatenate form field values, text strings and html to format a nice summary page:

Code Block
var totalAssets = TotalAutoValue.value + TotalBankValue.value + TotalRealEstateValue.value;

BasicSummaryMsg.value =  
"<b>Name:</b> " + FirstName.value + " " + LastName.value + "<br/>" + 
"<b>Phone:</b> " + Phone.value + "<br/>" + 
"<b>Email:</b> " + EmailAddress.value;

if (MilitaryOrCivilian.value === 'Military') { 
//Military 
DetailedSummaryMsg.value =  
"<b>Military Info:</b><br/>" +  "Military ID: " + MilitaryID.value + "<br/>" + 
"Rank: " + Rank.value + "<br/>" + 
"CurrentTitle: " + CurrentTitle.value + "<br/>" + 
"Years of Service: " + YearsOfService.value + "<br/>"; 
} else if (MilitaryOrCivilian.value === 'Civilian') { 
//Civilian 
DetailedSummaryMsg.value =  
"<b>Civilian Info:</b><br/>" +  
"SSN: " + SSN.value + "<br/>" + 
"Current Employer: " + CurrentEmployer.value + "<br/>" + 
"Current Title: " + CurrentTitle2.value + "<br/>" + 
"Start Date: " + StartDate.value + "<br/>"; 
}

FinancialSummaryMsg.value = 
"<b>Total Assets:</b> $" + totalAssets + 
"<br/>" + "Total Bank Assets: $" + TotalBankValue.value + "<br/>" + 
"Total Real Estate Value: $" + TotalRealEstateValue.value + "<br/>" + 
"Total Auto Value: $" + TotalAutoValue.value + "<br/>";

Note when using field values from repeat controls you must use a javascript var and assign the concatenation to the var and then the var to the 

Frevvoproduct
message control value. For example imagine you have a message control named Summary and a repeat control named Account:

Code Block
var acctSummary = ''; 
for (var i = 0; i < AreYouAttendingAccount.value.length; i++) 
{ 
    if (AreYouAttendingQ[i].value[0] === 'yes') {
        Message[i].value = Name.value + 
               ' is attending event #' + i; 
    } 
} 

String Concatenation

Message controls can be used in business rules to create summary information on your form from values entered into earlier form fields. This rule uses javascript variables to concatenate form field values, text strings and html to format a nice summary page:

Code Block
var totalAssets = TotalAutoValue.value + TotalBankValue.value + TotalRealEstateValue.value;

BasicSummaryMsg.value =  
"<b>Name:</b> " + FirstName.value + " " + LastName.value + "<br/>" + 
"<b>Phone:</b> " + Phone.value + "<br/>" + 
"<b>Email:</b> " + EmailAddress.value;

if (MilitaryOrCivilian.value === 'Military') { 
//Military 
DetailedSummaryMsg.value =  
"<b>Military Info:</b><br/>" +  "Military ID: " + MilitaryID.value + "<br/>" + 
"Rank: " + Rank.value + "<br/>" + 
"CurrentTitle: " + CurrentTitle.value + "<br/>" + 
"Years of Service: " + YearsOfService.value + "<br/>"; 
} else if (MilitaryOrCivilian.value === 'Civilian') { 
//Civilian 
DetailedSummaryMsg.value =  
"<b>Civilian Info:</b><br/>" +  
"SSN: " + SSN.value + "<br/>" + 
"Current Employer: " + CurrentEmployer.value + "<br/>" + 
"Current Title: " + CurrentTitle2.value + "<br/>" + 
"Start Date: " + StartDate.value + "<br/>"; 
}

FinancialSummaryMsg.value = 
"<b>Total Assets:</b> $" + totalAssets + 
"<br/>" + "Total Bank Assets: $" + TotalBankValue.value + "<br/>" + 
"Total Real Estate Value: $" + TotalRealEstateValue.value + "<br/>" + 
"Total Auto Value: $" + TotalAutoValue.value + "<br/>";

Note when using field values from repeat controls you must use a javascript var and assign the concatenation to the var and then the var to the 

Frevvoproduct
message control value. For example imagine you have a message control named Summary and a repeat control named Account:

Code Block
var acctSummary = ''; 
for (var i = 0; i < Account.value.length; i++) { 
    if (Q[i].value > 0) { 
        acctSummary = acctSummary + 'Account #' + i + ': ' + Account[i].value + '<br/>'; 
    } 
} 
Summary.value = acctSummary; 

Dynamic Labels, Help, Hints

You can set the value of control labels, help and hint dynamically in a rule. For example imagine you do not know the label, help or hint at design time but would rather set it dynamically when a user opens your form.

Code Block
if (form.load) 
{ 
  Text99.label = 'New Label'; 
  Text99.hint = 'New Hint'; 
  Text99.help = 'New Help'; 
}

In the above example the label, help and hint is still hard-coded. It's just being set from the rule rather than in the form designer controls' properties. To make this more useful you can initialize these properties from _data parameters:

Code Block
if (form.load)
{ 
   Text99.label = _data.getParameter('label'); 
   Text99.hint = _data.getParameter('hint'); 
   Text99.help = _data.getParameter('help'); 
}

Since _data.getParameter enables access to values passed to the form that are not bound to actual controls this is often a very useful pattern.

Visible/Invisible

This rule makes the message control nickNameThankYou visible when the user enters a value into the nickName input text control. And then hides the message control if the user deletes the value in nickName.

Code Block
if (nickName.value.length > 0 ) 
{ 
    nickNameThankYou.visible = true; 
} 
else 
{  
    nickNameThankYou.visible = false; 
} 

Visible/Invisible Section

Often section controls contain many inner controls. For example imagine a form that contains a person's medical history. One of the questions on the form asks if the patient uses a hearing aid. If they answer yes, then you want to collect more details on their hearing aid usage such as left ear, right ear, bilateral; hearing aid brand; etc. If they answer no then you want to hide all the questions specific to hearing aids. Also when the answer is yes you want to require them to answer all the hearing aid detailed questions.

Info

Avoid using message controls, images & video controls inside a section that contains other controls that you may want to make invisible. Since these three control types always contains a value, it can cause a section, or other controls in a section, to become required, and this can disable the form's Submit button. If you must include these controls, place them outside the section. Another alternative is to write rules for the individual controls within a section to set them to visible/invisible or required/not required

Imagine this example form has a section named HearingAid. By default HearingAid visible is set to false in the form designer.

When they answer yes, you must set HearingAid.visible=true AND also each required field inside the section to field.required = true. If they then change the answer to no then another rule makes the HearingAid.visible=false AND all the field.required=false. If the HearingAid section contains many child controls this rule becomes very long and tedious to write

We can simplify this by using the required property for sections. In the designer default all controls that must be answered inside HearingAid to required. Default the HearingAid section to not required and not visible. Your rule can be much simpler. By setting HearingAid.required=false all the inner controls recursively also become required=false.

Code Block
if (useAid.value === 'no') {
    // Hide 
    HearingAid.visible > 0) { 
        acctSummary = acctSummary + 'Account #' + i + ': ' + Account[i].value + '<br/>'; 
    } 
} 
Summary.value = acctSummary; 

Dynamic Labels, Help, Hints

You can set the value of control labels, help and hint dynamically in a rule. For example imagine you do not know the label, help or hint at design time but would rather set it dynamically when a user opens your form.

Code Block
if (form.load) 
{ 
  Text99.label = 'New Label'; 
  Text99.hint = 'New Hint'; 
  Text99.help = 'New Help'; 
}

In the above example the label, help and hint is still hard-coded. It's just being set from the rule rather than in the form designer controls' properties. To make this more useful you can initialize these properties from _data parameters:

Code Block
if (form.load)
{ 
   Text99.label = _data.getParameter('label'); 
   Text99.hint = _data.getParameter('hint'); 
   Text99.help = _data.getParameter('help'); 
}

Since _data.getParameter enables access to values passed to the form that are not bound to actual controls this is often a very useful pattern.

Visible/Invisible

This rule makes the message control nickNameThankYou visible when the user enters a value into the nickName input text control. And then hides the message control if the user deletes the value in nickName.

Code Block
if (nickName.value.length > 0 ) 
{ 
    nickNameThankYou.visible = true; 
} 
else 
{  
    nickNameThankYou.visible = false; 
} 

Visible/Invisible Section

Often section controls contain many inner controls. For example imagine a form that contains a person's medical history. One of the questions on the form asks if the patient uses a hearing aid. If they answer yes, then you want to collect more details on their hearing aid usage such as left ear, right ear, bilateral; hearing aid brand; etc. If they answer no then you want to hide all the questions specific to hearing aids. Also when the answer is yes you want to require them to answer all the hearing aid detailed questions.

Info

Avoid using message controls, images & video controls inside a section that contains other controls that you may want to make invisible. Since these three control types always contains a value, it can cause a section, or other controls in a section, to become required, and this can disable the form's Submit button. If you must include these controls, place them outside the section. Another alternative is to write rules for the individual controls within a section to set them to visible/invisible or required/not required

Imagine this example form has a section named HearingAid. By default HearingAid visible is set to false in the form designer.

When they answer yes, you must set HearingAid.visible=true AND also each required field inside the section to field.required = true. If they then change the answer to no then another rule makes the HearingAid.visible=false AND all the field.required=false. If the HearingAid section contains many child controls this rule becomes very long and tedious to write

We can simplify this by using the required property for sections. In the designer default all controls that must be answered inside HearingAid to required. Default the HearingAid section to not required and not visible. Your rule can be much simpler. By setting HearingAid.required=false all the inner controls recursively also become required=false.

Code Block
if (useAid.value === 'no') {
    // Hide 
    HearingAid.visible = false; 
    HearingAid.required = false; 
} else { 
    // Show 
    HearingAid.visible = true; 
    HearingAid.required = true; 
} 
Info

It is not currently possible to effect required for controls from XSD schema. This functionality will be added in a future release of

Frevvoproduct
. See the documentation for Data Sources and Schemas for details on implementing a Show/Hide rule with XSD controls.

Select Tab

This rule makes a specific tab the selected tab based on the choice of a radio control. The radio is named SelectTab and has three options: person, auto, home. The tabs are named personTab, autoTab and homeTab. Tabs also can be selected based on trigger controls or other input controls using the same method show here. 

Code Block
languagejavascript
if (SelectTab.value.length > 0)
{ 
    autoTab.selected = false; 
    homeTab.selected = false; 
    personTab.selected = false;

    if (SelectTab.value === 'Auto') 
        autoTab.selected = true; 
    } else if (SelectTab.value === 'Home') {
        homeTab.selected = true;
    } else {
        personTab.selected = true;
    }
}

Next Tab

This form contains a trigger control at the bottom of each tab labeled "Next". When "Next" is clicked the trigger rule executes and makes the next tab the selected tab. This assists the user in navigating through the form. The Tabs are named T1, T2, T3, T4. The trigger controls are named C1, C2, C3

Code Block
// Navigate Tabs 
if (C1.clicked) { 
    T2.selected = true; 
} else if (C2.clicked) {
    T3.selected = true; 
} else if (C3.clicked) { 
    T4.selected = true; 
} 

Expand/Collapse Section

This form has three sections. The first section is expanded and the 2nd and 3rd are collapsed. When the user files in the 1st section they click a "Next" trigger control which causes that section to collapse and the next section to expand. The trigger controls are named next1 and next2. And the sections are named: step1, step2, step3. 

Code Block
if(next1.clicked) 
{ 
    step1.expanded = false; 
    HearingAidstep2.requiredexpanded = falsetrue; 
}
else {
if(next2.clicked) 
  { 
// Show      HearingAid.visiblestep2.expanded = truefalse; 
    HearingAidstep3.requiredexpanded = true; 
} 
Info

It is not currently possible to effect required for controls from XSD schema. This functionality will be added in a future release of

Frevvoproduct
. See the documentation for Data Sources and Schemas for details on implementing a Show/Hide rule with XSD controls.

Select Tab

...

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.

Code Block
languagejavascript
var x;
if (SelectTab.value.length > 0form.load) { 
    autoTab.selected = false;// User Information 
    homeTabId.selectedvalue = false; _data.getParameter('subject.id'); // Username 
   personTab FirstName.selectedvalue = false_data.getParameter('subject.first.name'); 
    if (SelectTabLastName.value === 'Auto_data.getParameter('subject.last.name'); 
    Email.value    autoTab.selected = true;= _data.getParameter('subject.email'); 
 
    var }roles else if= _data.getParameter (SelectTab.value === 'Home') {
   "subject.roles"); 
    if (roles) { 
   homeTab.selected = true;   eval ('x=' }+ elseroles); {
        personTabRoles.selectedoptions = truex; 
    } 
}

Next Tab

This form contains a trigger control at the bottom of each tab labeled "Next". When "Next" is clicked the trigger rule executes and makes the next tab the selected tab. This assists the user in navigating through the form. The Tabs are named T1, T2, T3, T4. The trigger controls are named C1, C2, C3

...

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.

Code Block
if (form.load) { 
    if (_data.getParameter('flow.activity.name') === 'Manager Review')  {
        T4Review.selectedvisible = true; 
    } 

Expand/Collapse Section

This form has three sections. The first section is expanded and the 2nd and 3rd are collapsed. When the user files in the 1st section they click a "Next" trigger control which causes that section to collapse and the next section to expand. The trigger controls are named next1 and next2. And the sections are named: step1, step2, step3. 

Code Block
if(next1.clicked}

Multiple Choice

This rule makes the appropriate input text controls visible depending on the choice a user makes in a radio option controls searchChoice.

Code Block
if (searchChoice.value === 'Organizations') 
{
     step1orgname.expandedvisible = false; 
    step2.expanded = true; 
}

if(next2.clicked) 
{true; 
    firstname.visible = false; 
    step2lastname.expandedvisible = false; 
    step3clientId.expandedvisible = truefalse; 
}

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.

Code Block
languagejavascript
var x; 
else if (form.loadsearchChoice.value === 'Individuals') 
{ 
    // User Informationorgname.visible = false; 
    Idfirstname.valuevisible = _data.getParameter('subject.id'); // Usernametrue; 
     FirstNamelastname.valuevisible = _data.getParameter('subject.first.name')true; 
    LastNameclientId.valuevisible = _data.getParameter('subject.last.name')false; 
} else if  Email(searchChoice.value === _data.getParameter('subject.email'Client ID'); 
 { 
   var rolesorgname.visible = _data.getParameter ("subject.roles")false; 
    if (roles) {firstname.visible = false; 
        eval ('x=' + roles);lastname.visible = false; 
    clientId.visible = true; 
 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.

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

Multiple Choice

This rule makes the appropriate input text controls visible depending on the choice a user makes in a radio option controls searchChoice.

Code Block
if (searchChoice.value === 'Organizations') 
{
    orgname.visible = true; 
    firstname.visible = false; 
    lastname.visible = false; 
    clientId.visible = false; 
} 
else if (searchChoice.value === 'Individuals') 
{ 
    orgname.visible = false; 
    firstname.visible = true; 
    lastname.visible = true; 
    clientId.visible = false; 
} else if (searchChoice.value === 'Client ID'} 

Dynamic Options

Selection controls' (radios, checkboxes, dropdowns, T/F) options can be set dynamically via rules rather than statically via the control's options property. However if the control comes from an XSD schema data source rather than one of the standard palette controls, then the designer must take care to not set the options to something outside of what is valid for that schema element. For example if your XSD has a string enumeration and list valid options as 'red', 'green', and 'blue', then you should not use a rule to dynamically set the options to 'small', 'medium', 'large'. If you do then then your form will not work correctly in use mode. If a user selects the option 'small' they will get a validation error on the form. This is because 'small' is not one of the options allowed by your underlying XSD schema.

Triggers & Dynamic Options

This rule is executed when the user clicks the trigger controls with Name ''search''. It then dynamically sets options on a dropdown list control with Name coffeeShopList.

Code Block
languagejavascript
if (search.clicked) 
{ 
    orgnamecoffeeShopList.visibleoptions = false; 
    firstname.visible = false; 
    lastname.visible = false; 
    clientId.visible = true; 
} 

Dynamic Options

Selection controls' (radios, checkboxes, dropdowns, T/F) options can be set dynamically via rules rather than statically via the control's options property. However if the control comes from an XSD schema data source rather than one of the standard palette controls, then the designer must take care to not set the options to something outside of what is valid for that schema element. For example if your XSD has a string enumeration and list valid options as 'red', 'green', and 'blue', then you should not use a rule to dynamically set the options to 'small', 'medium', 'large'. If you do then then your form will not work correctly in use mode. If a user selects the option 'small' they will get a validation error on the form. This is because 'small' is not one of the options allowed by your underlying XSD schema.

Triggers & Dynamic Options

This rule is executed when the user clicks the trigger controls with Name ''search''. It then dynamically sets options on a dropdown list control with Name coffeeShopList.

Code Block
languagejavascript
if (search.clicked['Koffee', 'Starbucks', 'Willoughbys', 'Dunkin Donuts'];
} 

Now replace the hard coded list of coffee shops with a rule that invokes an http.get. This must return an X-JSON header which contains a JSON object. The object is evaluated and assigned to the variable x. In this case the JSON object contains an options field of type array. See the section on dynamic content for more details.

Code Block
languagejavascript
var x;
if (search.clicked) 
{ 
    eval('x=' + http.get('http://(your webhost)/getCoffeeShopList'));  
    coffeeShopList.options = x.options; 
} 
Tip

Triggers do not work in repeating items.

Value Change & Dynamic Options

This rule dynamically sets the options in a dropdown list based on the value selected in another form field. This form contains three fields named Products, Series and Model. The series options are set dynamically based on the product selection. Also when a new product is selected we enable the series dropdown and both clear and disable the model dropdown. This form contains other rules which set the models based on the selected series. 

Code Block
if (product.value === 'Laserjet Printers') 
{ 
    coffeeShopListseries.options = ['Koffee', 'Starbucks', 'Willoughbys', 'Dunkin Donuts'];
} 

Now replace the hard coded list of coffee shops with a rule that invokes an http.get. This must return an X-JSON header which contains a JSON object. The object is evaluated and assigned to the variable x. In this case the JSON object contains an options field of type array. See the section on dynamic content for more details.

Code Block
languagejavascript
var x;
if (search.clicked) 
{ 
    eval('x=' + http.get('http://(your webhost)/getCoffeeShopList'));  
    coffeeShopList.options = x.options; 
} 
Tip

Triggers do not work in repeating items.

Value Change & Dynamic Options

This rule dynamically sets the options in a dropdown list based on the value selected in another form field. This form contains three fields named Products, Series and Model. The series options are set dynamically based on the product selection. Also when a new product is selected we enable the series dropdown and both clear and disable the model dropdown. This form contains other rules which set the models based on the selected series. 

Code Block
if (product.value === 'Laserjet Printers') 
{ 
    series.options = [' ', 'Laserjet5 series', 'Laserjet6 series']; 
    series.enabled = true; 
    model.options = []; 
    model.enabled = false; 
} 

Dynamic Control Initialization using JSON

This rule handles the case of initializing multiple control values based on the selection of a dropdown control. It handles this case better than using a long if/else construct by using a JSON string. First add options to the dropdown named SalesRep in the format <value>=<label> where <value> will be used as an index key into a JSON array of details about each person.

Code Block
Megan=Megan Smith 
Jim=Jim Brown 
Nancy=Nancy Jones 
Brian=Brian Jones 

Then write a rule that first sets up a javascript JSON syntax array with the contact information for each person. The rules then uses the dropdown value to index into the contantInfo array to set the details for the selected person into four other form controls.

Code Block
languagejavascript
/*member '' Brian Jim Megan Nancy cell email phone */
 
var contactInfo = { 
    "' ', 'Laserjet5 series', 'Laserjet6 series']; 
    series.enabled = true; 
    model.options = []; 
    model.enabled = false; 
} 

Dynamic Control Initialization using JSON

This rule handles the case of initializing multiple control values based on the selection of a dropdown control. It handles this case better than using a long if/else construct by using a JSON string. First add options to the dropdown named SalesRep in the format <value>=<label> where <value> will be used as an index key into a JSON array of details about each person.

Code Block
Megan=Megan Smith 
Jim=Jim Brown 
Nancy=Nancy Jones 
Brian=Brian Jones 

Then write a rule that first sets up a javascript JSON syntax array with the contact information for each person. The rules then uses the dropdown value to index into the contactInfo array to set the details for the selected person into four other form controls.

Code Block
languagejavascript
/*member '' Brian Jim Megan Nancy cell email phone */
 
var contactInfo = { 
    "" : {  
        name : "", 
        email : "", 
        phone : "", 
        cell : "" 
    }, 
    "Megan" : {  
         name : "Megan Smith", 
         email : MSmith@mycompany.com, 
         phone : "(203) 694-2439 Ext. 516", 
         cell : "(203) 337-3242" 
    }, 
    "Jim" : {  
        name : "Jim Brown", 
        email : ""jim@comcast.net, 
        phone : "203-208-2999", 
        cell : "" 
    }, 
    "MeganNancy" : {  
         name : "MeganNancy SmithJones", 
         email : MSmith@mycompanynancy@snet.comnet, 
         phone : "(203) 694-2439 Ext. 516-208-2991",  
        cell : "(203) 337-3242" 
    }, 
    "JimBrian" : {  
        name : "JimBrian BrownJones", 
        email : jim@comcastBJones@mycompany.netcom, 
        phone : "203-208-2999", 
        cell : "" 
    }, 
    "Nancy" : : "203-748-6502", 
        cell : "" 
    } 
};
 
var repId = SalesRep.value;
SalesRepName.value = contactInfo[repId].name; 
SalesRepEmail.value = contactInfo[repId].email; 
SalesRepPhone.value = contactInfo[repId].phone; 
SalesRepCell.value = contactInfo[repId].cell;

Try this simple Clinic Location form which uses this approach to initialize its controls.

Verify User

This rule executes when the user enters a value into the Username text field. It uses the built-in isUniqueUserId() method that returns false if the user already exists. If the user already exists this rule then sets the value of a message control, makes that message control visible on the form and sets the Username valid property to false so that Username field displays as invalid to guide the user to make a correction. See the section on dynamic content for more details.

Code Block
languagejavascript
if (U.value.length > 0) {  
        name : "Nancy Jones", 
        email : nancy@snet.net, 
        phone : "203-208-2991",  
        cell : "" 
    }, 
    "Brian" : if (frevvo.isUniqueUserId(user.value, tenant.value) === false) { 
        M.value name= 'User: "Brian Jones", 
        email : BJones@mycompany.com,' + U.value + ' already exists'; 
        phoneM.visible : "203-748-6502",= true; 
        cellU.valid := ""false; 
    } else };{  
var repId = SalesRep.value; SalesRepName.value = contactInfo[repId].name;  SalesRepEmailM.valuevisible = contactInfo[repId].email;false; 
 SalesRepPhone.value = contactInfo[repId].phone; } SalesRepCell.value
= contactInfo[repId].cell;

Try this simple Clinic Location form which uses this approach to initialize its controls.

Verify User

This rule executes when the user enters a value into the Username text field. It uses the built-in isUniqueUserId() method that returns false if the user already exists. If the user already exists this rule then sets the value of a message control, makes that message control visible on the form and sets the Username valid property to false so that Username field displays as invalid to guide the user to make a correction. See the section on dynamic content for more details.

Code Block
languagejavascript
if (U.value.length > 0) {} 

Digital Signature

This form uses a rule to pass a username and password to a LDAP Active Directory authentication service. If authentication fails the form makes an error message control visible. If authentication succeeds the form disables the username form field and replaces the password field with a date field set to the current date. The form contains a trigger control named sign, username and password fields named u and p respectively, a date field named d and a message field named m.

Image Added

Code Block
languagejavascript
/*member auth */
var x;
 
if (sign.clicked) { 
    // passwords may contain characters that need url encoding 
    var p_encode = encodeURIComponent(p.value);

    eval('x=' + http.get('http://(your webhost)/authServices/signForm?username=' + 
                         if (frevvo.isUniqueUserId(user.value, tenant.value) === falseu.value + '&password=' + p_encode));

    if (x.auth) { 
        M.value = 'User: ' + U.value + ' already exists';var dt = new Date(); 
        var day = dt.getDate(); 
        var month = Mdt.visiblegetMonth() =+ true1; 
        var U.validyear = false; 
 dt.getFullYear(); 
 } else {          M.visibled.value = false;month + '-' + day + }'-' 
} 

Digital Signature

This form uses a rule to pass a username and password to a LDAP Active Directory authentication service. If authentication fails the form makes an error message control visible. If authentication succeeds the form disables the username form field and replaces the password field with a date field set to the current date. The form contains a trigger control named sign, username and password fields named u and p respectively, a date field named d and a message field named m.

Image Removed

Code Block
languagejavascript
/*member auth */
var x;
 
if (sign.clicked) {+ year;

        d.visible = true; 
     // passwords may containu.enabled characters= thatfalse; need
url encoding      var p_encode.visible = encodeURIComponent(p.value);false; 
      eval('x=' + http.get('http://(your webhost)/authServices/signForm?username=' + sign.visible = false; 
        m.visible = false; 
    } else { 
     um.valuevisible + '&password=' + p_encode));= true; 
    } 
if (x.auth) {}

The authService is an example HTTP servlet that returns a JSON response.

Code Block
public void doGet (HttpServletRequest request, HttpServletResponse response) 
    throws ServletException, IOException {
 
 var dt = new Date();try { 
        varString dayusername = dtrequest.getDategetParameter(REQUEST_SIG_USERNAME); 
        varString monthpassword = dtrequest.getMonthgetParameter() + 1REQUEST_SIG_PASSWORD); 
        varpassword year = dtURLDecoder.getFullYear(decode(password, "UTF-8"); 
        d.value = month + '-' + day + '-' + year;

  // Authenticate Signature 
        authenticateUser(response, username, password);  
   d.visible =} true;catch (Exception e) { 
     u.enabled = false; throw new ServletException(e); 
    } p.visible
=}
false;
private void authenticateUser(HttpServletResponse response, String u, String p) { sign.visible
= false;   if (realm.authenticate(u, p) === null) 
 m.visible = false;     response.addHeader(RESPONSE_JSON_HEADER, "{auth:false}"); else
{    else 
m.visible  = true;     response.addHeader(RESPONSE_JSON_HEADER, "{auth:true}"); 
} 

Here's another example form that requires a doctor's signature. This shows how the form works in use mode. The first image contains a dropdown to select one of the doctor's authorized to sign the form and a text control where they enter their PIN code.

The authService is an example HTTP servlet that returns a JSON response.

Code Block
public void doGet (HttpServletRequest request, HttpServletResponse response) 
    throws ServletException, IOException {
 
    try { 
        String username = request.getParameter(REQUEST_SIG_USERNAME); 
        String password = request.getParameter(REQUEST_SIG_PASSWORD); 
        password = URLDecoder.decode(password, "UTF-8"); 
        // Authenticate Signature 
        authenticateUser(response, username, password);  
    } catch (Exception e) { 
        throw new ServletException(e); 
    } 
}

private void authenticateUser(HttpServletResponse response, String u, String p) { 
    if (realm.authenticate(u, p) === null) 
        response.addHeader(RESPONSE_JSON_HEADER, "{auth:false}"); 
    else 
        response.addHeader(RESPONSE_JSON_HEADER, "{auth:true}"); 
} 

Here's another example form that requires a doctor's signature. This shows how the form works in use mode. The first image contains a dropdown to select one of the doctor's authorized to sign the form and a text control where they enter their PIN code.

Image Removed

This image shows the case where the doctor entered an invalid PIN and the error message becomes visible.

Image Removed

This image shows the case of a valid PIN. Today's date is entered into the date control via the rule and made visible and disabled from edit. The username dropdown is disabled and the PIN and Sign controls are hidden.

Image Removed

Calculate Net Worth

This form contains two rules. One is adding values entered into a column of assets and a column of liabilities and calculatng netWorth. The 2nd rule is checking the value of netWorth and displaying an error message and marking netWorth invalid if liabilities exceed assets since the form designer does not want the form to be submitted in that state.

Code Block
if (netWorth.value < 0) 
{ 
    assetsExceedLiabilitiesMsg.visible = true; 
    netWorth.valid = false; 
} 
else 
{ 
    assetsExceedLiabilitiesMsg.visible = false; 
    netWorth.valid = true; 
} 

When a rule sets <control>.invalid the control background turns red and the submit button greys out just as if the user had entered an invalid value into a phone control. 

Frevvoproduct
treats it exactly the same way. This is a good way to dynamically control your form's valid state.

Dates and Times

Working with dates and times is very common in most forms. The samples below show you how to create the most common business logic with dates and times. 

Info

Frevvoproduct
 dates can be set in the user's local timezone by using the built-in date, time and date/time methods such as frevvo.currentDateTime(). See Built-in Methods for a complete method list. If you use the base javascript date object you will get UTC timezone.

Note

Many of the samples below use the javascript Date() object. Since business rules run on the form server these dates will be in the timezone where the form server was installed. There are techniques below to convert to different timezones as you need.

The Date/Time control uses a "T" to separate the date and time when initializing from a business rule. For example, the syntax shown below will initialize a Date/Time control named DtTm to May 15, 2012 at 4:20 am.

Code Block
languagejavascript
DtTm.value = "5/15/2012T4:20";

Date controls will successfully initialize via a rule or an xml document when the data provided has a single digit for the month and/or the day. The rule below can be used to initialize a form with a date and date/time control. Notice the Date.Value and Date+Time.value rule identifiers have a single digit for the month.  

Code Block
if(form.load)
{
Date.value = "2011-2-10";
Date_Time.value = "2011-1-23T20:20:20";
}

The Date/Time control will display an "Invalid Value" error if single digits for the month and/or day are used .

Image Removed

 Change the Date_Time.value = "2011-1-23T20:20:20"; to Date_Time.value = "2011-01-23T20:20:20"; in the rule or the xml document for successful initialization.

...

Image Added

This image shows the case where the doctor entered an invalid PIN and the error message becomes visible.

Image Added

This image shows the case of a valid PIN. Today's date is entered into the date control via the rule and made visible and disabled from edit. The username dropdown is disabled and the PIN and Sign controls are hidden.

Image Added

Calculate Net Worth

This form contains two rules. One is adding values entered into a column of assets and a column of liabilities and calculating netWorth. The 2nd rule is checking the value of netWorth and displaying an error message and marking netWorth invalid if liabilities exceed assets since the form designer does not want the form to be submitted in that state.

Code Block
if (netWorth.value < 0) 
{ 
    assetsExceedLiabilitiesMsg.visible = true; 
    netWorth.valid = false; 
} 
else 
{ 
    assetsExceedLiabilitiesMsg.visible = false; 
    netWorth.valid = true; 
} 

When a rule sets <control>.invalid the control background turns red and the submit button grays out just as if the user had entered an invalid value into a phone control. 

Frevvoproduct
treats it exactly the same way. This is a good way to dynamically control your form's valid state.

Dates and Times

Working with dates and times is very common in most forms. The samples below show you how to create the most common business logic with dates and times. 

Info

Frevvoproduct
 dates can be set in the user's local timezone by using the built-in date, time and date/time methods such as frevvo.currentDateTime(). See Built-in Methods for a complete method list. If you use the base javascript date object you will get UTC timezone.

Note

Many of the samples below use the javascript Date() object. Since business rules run on the form server these dates will be in the timezone where the form server was installed. There are techniques below to convert to different timezones as you need.

The Date/Time control uses a "T" to separate the date and time when initializing from a business rule. For example, the syntax shown below will initialize a Date/Time control named DtTm to May 15, 2012 at 4:20 am.

Code Block
languagejavascript
DtTm.value = "5/15/2012T4:20";

Date controls will successfully initialize via a rule or an xml document when the data provided has a single digit for the month and/or the day. The rule below can be used to initialize a form with a date and date/time control. Notice the Date.Value and Date+Time.value rule identifiers have a single digit for the month.  

Code Block
if(form.load)
{
Date.value = "2011-2-10";
Date_Time.value = "2011-1-23T20:20:20";
}

The Date/Time control will display an "Invalid Value" error if single digits for the month and/or day are used .

Image Added

 Change the Date_Time.value = "2011-1-23T20:20:20"; to Date_Time.value = "2011-01-23T20:20:20"; in the rule or the xml document for successful initialization.

Warning

Rules initializing time and date/time controls will not work in a form.load rule unless you specify a timezone on the form's Url via the _formTz Url parameter. This is because the form server needs to know the timezone in which to return the date and time. If you do not specify a _formTz the methods will return null and the control values will remain blank. The timezone strings can be found here. For example, to specify Eastern time: &_formTz=America/NewYork. This URL parameter is not needed if your form/flow only contains Date controls.

Age

This example form automatically determines today's date and then calculates the person's age in the control named 'Age' when they enter their birth date into the control named 'BirthDate'.

Image Added

Code Block
if (BirthDate.value.length > 0) {
  var today = new Date();
  var dob = BirthDate.value.split('-'); 
  var dob2 = new Date(dob[0],dob[1]-1,dob[2]);
  var age = today.getFullYear() - dob2.getFullYear();
  if (today.getMonth() < dob2.getMonth() || 
     (today.getMonth() === dob2.getMonth() &&
      today.getDate() < dob2.getDate())) {
    age -= 1;
  }
  if (age >= 0) {
     Age.value = age;
  } else {
     Age.value = null;
  }
}

Duration

This form initializes the hospital discharge date using a rule, and when the user enters the admission date a 2nd rule calculates the number of days the patient stayed in the hospital.

...

Code Block
languagejavascript
/ Calculate Hospital Stay Duration 
if (A.value !== '' && D.value !== '') { 
    var da = A.value.split('-'); 
    var Ams = new Date(da[0],da[1],da[2]); 
    da = D.value.split('-'); 
    var Dms = new Date(da[0],da[1],da[2]);
 
    if (Ams > Dms) { 
        Days.value = 'Discharge date must be after Admission Date'; 
    } else { 
        Days.value = (Dms - Ams) / (1000*60*60*24) + ' days'; 
    } 
}

 

Duration (between Date/Time)

Here is a rule example to calculate the time difference between two Date/Time values in hours:minutes format :

...

Today's Date and Time

Use

Frevvoproduct
' s built-in date and time methods to set your date, time, and date/time controls to the current date and time in the user's local timezone.

...

This rule makes the date control invalid if the date entered isn't before today's date.

Code Block
// frevvo currentDate method gets today in users timezone
var today = frevvo.currentDate().split('-');
var today_date = new Date(today[0], today[1]-1, today[2]); 
var bd = DOB.value.split('-'); 
var bd_date = new Date(bd[0],bd[1]-1,bd[2]);

if (bd_date.getTime() > today.getTime()_date) { 
    MyMsg.value = 'Birth Date must be earlier than today!!!!';   
    DOB.valid = false; 
} else { 
    MyMsg.value = 'This is a good Birth Date: ' + DOB.value;; 
    DOB.valid = true; 
}
Note

Use frevvo.currentDate() rather than the javascript new Date() since the latter gets today's date in the Live Forms server's timezone while the frevvo currentDate() correctly gets today's date in the user's timezone.

Date no more then 14 days from Today

...

Code Block
if (EventStartDate.value !== "") { 
    var date1 = DateUtil.today(); 
    var date2 = EventStartDate.value; 
    date1 = date1.split("-"); 
    date2 = date2.split("-"); 
    var sDate = new Date(date1[0]+"/"+date1[1]+"/"+date1[2]); 
    var eDate = new Date(date2[0]+"/"+date2[1]+"/"+date2[2]); 
    var days = Math.round((eDate-sDate)/86400000);
 
if (!eval(parseInt(days,10) > parseInt(-30,10))) { 
    EventStartDate.valid = false; 
    EventStartDate.status = "The date entered can only go back a maximum of 30 days from the current date. Please try again.";
 
} else { 
    EventStartDate.valid = true; 
}
}

 Add # of Years, Months or Days to a Date

Here is a rule that will add 3 years to a given date.  For example, to calculate the expiration date of a three year contract by adding three years to the starting date, your form could have two date controls, one used to enter the starting date and the other to show the contract expiration date. This rule will take the date from the StartingDate field, add 3 years to it and populate the result in a field named ExpirationDate.

...

Code Block
Traveler1.visible = false;
Traveler2.visible = false;
Traveler3.visible = false;
Traveler1.required = false;
Traveler2.required = false;
Traveler3.required = false;

for (var i=0; i < NumTickets.value; i++) {
 if (i >= 0) {
  Traveler1.visible = true;
  Traveler1.required = true;
 }
 if (i >= 1) {
  Traveler2.visible = true;
  Traveler2.required = true;
 }
 if (i >= 2) {
  Traveler3.visible = true;
  Traveler3.required = true;
 }
}

 

Tables

Tables are identical to repeat controls when referenced in business rules. Tables are a grid layout of repeating items. All the rule examples in this chapter that discuss repeats apply also to tables. The one important note is that you cannot explicitly name the repeat control inside your table. The repeat control inside a table is automatically named as <TableName>Repeat. For example a table named Expense automatically has a repeat named ExpenseRepeat. The rule ExpenseRepeat.itemAdded and ExpenseRepeat.itemIndex references an item added to your table and that item's index respectively.

...

You can hide the  minus icon of a table row using a business rule. For example, the designer may not want to allow users to delete rows in a table that is populated from a back end system. Hiding the delete icon on these rows eliminates accidental deletion. The rule must set the table rows deletable attribute. You will not see this property listed on the Table control property pane but it will be listed in the Form Outline tool. 

Let's take a look at a simple example. Users are instructed to enter a capital Y in a table if they are planning on calling a customer. The user enters the "Y" then tabs to the company name column. The minus icon for that row will disappear.  

Image Removed

Here is the rule:

...

must set the table rows deletable attribute. You will not see this property listed on the Table control property pane but it will be listed in the Form Outline tool. 

Let's take a look at a simple example. Users are instructed to enter a capital Y in a table if they are planning on calling a customer. The user enters the "Y" then tabs to the company name column. The minus icon for that row will disappear.  

In this example, the name of the table control is CustomerTable and column 0 in the table is named ContactCustomer.

Image Added

Here is the rule:

Code Block
for (var i=0; i<ContactCustomer.value.length; i++) {
    if (ContactCustomer[i].value === "Y") {
        CustomerTableItem[i].deletable = false;
    } else {
        CustomerTableItem[i].deletable = true;
    }
}

Notice the TableItem deletable property is set to false when a capital Y is entered in the first column. This will remove the minus icon for that row of the table. The for loop cycles through the table rows until the Max# property is reached. 

Clearing Values in a Table

This rule clears the values from all rows in a table. Notice the For loop that iterates over all the rows. Inside the loop a null value is assigned to all the columns in the table row.

Code Block
languagejs
 for (var i = 0; i < Col0.value.length; i++) { 
   if (ContactCustomerCol0[i].value === "Y") {
        CustomerTableItem[i].deletable = false;
    } else {
    null;
    Col1[i].value = null;
    CustomerTableItemCol2[i].deletablevalue = truenull;
    } }

...

You cannot clear an entire table from a rule.

form.load

Rules can be used to initialize field values. This is a very useful feature and is often used to dynamically populate dropdown options from a database. Rules using form.load are triggered when a form first loads and when a workflow is loaded from a task list.

...

Code Block
/*member nextid results */
var x;
 
if (form.load) { 
    var readmethod = 
'http://www.frevvo.com/google/spreadsheets/query/u/<google username>/p/<google password>/s/SequentialNumberGenerator/w/Sheet1?media=json&query=formname="Checkbook"';
 
    var updatemethod = 
'http://www.frevvo.com/google/spreadsheets/update/u/<google username>/p/<google password>/s/SequentialNumberGenerator/w/Sheet1?media=json&query=formname="Checkbook"';
 
 
    eval('x=' + http.get(readmethod)); 
 
    var id = 'unknown'; 
 
    if (x.results === null) 
        { CheckNum.value = 'error'; 
    } else if (x.results.length === 0) { 
        CheckNum.value = 'No Match'; 
    } else { 
    id = x.results[0].nextid; 
    CheckNum.value = id; 
    id = id*1 + 1; 
    } 
 
    if (id !== 'unknown') { 
    eval('x=' + http.getput(updatemethod + '&updates=nextid=' + id + '&_method=put')); 
    } 
}

Unique ID

Forms such as invoices, bills of lading, etc often need to be stamped with a unique ID. The Sequential Number example is one approach, however it has some limitations. One is that you must guarantee that only one person at a time is filling out your form. This is because there is no mutex around the read and update of the Google spreadsheet cell.

...

A rule can dynamically display an image uploaded to your form via the upload control. In this example the upload control is named 'u'. The form also must contain a message control as a place holder for displaying the uploaded image. The rule dynamically creates a URL to the uploaded image in the

Frevvoproduct
temporary attachment repository. The upload control's value 'u.value' is a GUID that uniquely identifies the attachment. The uploaded image will be included in the submissions pdf.

Code Block
languagejavascript
if (u.value.length > 0) {
  var baseUrl = _data.getParameter('_frevvo_base_url') + 
      ""/frevvo/web/tn/" +
      _data.getParameter('tn.id') +
      "/user/"+_data.getParameter('user.id') +
      "/app/"+_data.getParameter('app.id') +
      "/form/"+_data.getParameter('form.id');
 
  im.value = "'<img src="'" +
         baseUrl + "'/attachment/"' + u.value+"'/does_not_matter'"/>"';
} 

Here is the example form before and after the user has upload the orangegrovefrevvo.logo,orange.png image:

Section
Column

Column

...

The section control contains controls that are the search critiera criteria for finding a RACF ID based on other pieces of information you may know about an employee such as name, type, email address. The values entered into the search criteria can be partial values. For instance entering a name "Smith" will find all employees whose name contains the letters "Smith". If you also select email, it will find all employees whose name contains "Smith" and have an email address containing the string "frevvo".

...