Section | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
...
Code Block |
---|
var x, x1, x2; if (Num.value > 0) { var nStr = Num.value.toFixed(2); nStr += ''; x = nStr.split('.'); x1 = x[0]; 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
This rule is not yet supported in the Visual Rules Builder and thus still requires some JavaScript.
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; |
...
Rounding a Number to a Specified Number of Decimal Places
Let's say you have a Time Sheet where you collect the number of hours worked per day and total them in a Line Total field. Your form consists of Number controls for the hours and a Number control for the total. When testing your form, you enter values with decimal points and notice the total unexpectedly calculates to a number with many decimal places.
Section | ||||||
---|---|---|---|---|---|---|
|
Another approach would be to assign Patterns that limit the number of decimal places to the fields.
Textarea Max Length
This rule is not yet supported in the Visual Rules Builder and thus still requires some JavaScript.
You can build forms/flows In that meet Section 508 and WCAG 2.0 accessibility standards. Accessible forms/flows can assist users with visual and motor impairments. When the Accessible property is enabled for a form/flow, the error, "You can't leave this empty <control name>" displays, if users move ahead from a required field without filling it. The status property for the empty control becomes invalid and sets the error message. Normally, the status property can be used in a business rule. For example, let's say a form has a text control named 't', and a message control named "m". If you write a rule to update the message field (control named m) with the STATUS of the required/invalid control (control named t), as shown below, it will not work because the "You can't leave this empty" message for a required control is not treated as it's status.
Code Block | ||
---|---|---|
| ||
if(!t.valid)
{
m.value = t.status;
} |
If the rule is written this way, it will fill the message control with the errmsg from the invalid text control.
Code Block | ||
---|---|---|
| ||
if (!t.valid) {
if (t.value.length === 0) {
m.value = "You can't leave this empty."
} else {
m.value = t.status;
}
} |
...
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; |
Required Field Status in Accessible Forms
This rule is not yet supported in the Visual Rules Builder and thus still requires some JavaScript.
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.
...
You can build forms/flows In that meet Section 508 and WCAG 2.0 accessibility standards. Accessible forms/flows can assist users with visual and motor impairments. When the Accessible property is enabled for a form/flow, the error, "You can't leave this empty <control name>" displays, if users move ahead from a required field without filling it. The status property for the empty control becomes invalid and sets the error message. Normally, the status property can be used in a business rule. For example, let's say a form has a text control named 't', and a message control named "m". If you write a rule to update the message field (control named m) with the STATUS of the required/invalid control (control named t), as shown below, it will not work because the "You can't leave this empty" message for a required control is not treated as it's status.
Code Block | ||
---|---|---|
| ||
if(!t.valid)
{
m.value = t.status;
} |
If the rule is written this way, it will fill the message control with the errmsg from the invalid text control.
Code Block | ||
---|---|---|
| ||
if (!t.valid) {
if (t.value.length === 0) {
m.value = "You can't leave this empty."
} else {
m.value = t.status;
}
} |
Textarea newline vs break
This rule is not yet supported in the Visual Rules Builder and thus still requires some JavaScript.
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; |
Selection Controls
Dropdowns, Checkboxes, Radio, ComboBox and T/F controls are selection controls. Populating selection control options to to create dynamic or static pick lists is a very common feature. Here are some of the top reasons you may want to do this:
...
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) { for (xselectedcolors in RGB.options) { = selectedcolors + ' ' + lab; var opt = RGB.options[x]; } } } varSelectedColors.value val= opt.split('=')[0]; var lab= opt.split('=')[1= selectedcolors; |
Set Options for a Checkbox based on Values Selected in another Checkbox
This rule is not yet supported in the Visual Rules Builder and thus still requires some JavaScript. This rule will take values selected in one checkbox control and populates those as options in a second checkbox control. For example, a checkbox control (Services) displays all available services. The second checkbox (Selected Services) will display as options the values selected in Services. One scenario you might use this is to customize an employee scheduling form. In Step 1 of the flow the Coordinator picks the offered services from the full Program Service list. In Step 2 the Employee sees only the smaller list to select from.
Code Block |
---|
var opts = ['']; for (var i = 0; i if (v === val) < ProgramService.value.length; i++ ){ var v = ProgramService.value[i].replace(/_/g," "); selectedcolors = selectedcolorsopts[i] = ProgramService[i].value + '"=" ' + lab; v; } SelectedPS.options = opts; var }event = } SelectedColors.value = selectedcolorsform.load; |
Retrieving or Setting the Comment Property for Selection Controls
...
Use the today and timeofday functions in the Rule Builder to populate fields a Date field with the current date and a Time field with the current time on form load. Remember to select Date or Time from the Date Control Type dropdown.
Here is what the rule looks like in the Rule List
Use the built-in date/time method now function to set your date/time controls to the current date and time in the user's local timezone on formload.
...
Note |
---|
The currentTime(), currentDate() and currentDateTime() 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. For example &formTz=America/New_York will set the control values to the current date and time in the eastern timezone. |
...
You may want to calculate a date in a workflow based on a five day work week. This is a common business scenario and may be helpful if you are using the Escalations feature. It is not possible to select calendar or working days for the Days interval of the Escalation feature at this time but this enhancement is planned for a future release. As a work-around, you can calculate X number of working days from the current date, and set that date in a Date control on your form. Then while configuring escalations, use the ‘Complete By’ condition and select the Date control.
Here is the business function/rule that will add 3 working days to the current date to give you the escalation date. Copy/paste the entire rule including the function in the Rule Editor. Substitute the name of your date control for <your date control>:
Code Block | ||
---|---|---|
| ||
function calcWorkingDays(fromDate, days) { var count = 0; while (count < days) { fromDate.setDate(fromDate.getDate() + 1); if (fromDate.getDay() !== 0 && fromDate.getDay() !== 6) { // Skip weekends count++; } } return fromDate; } if (form.load && <your date control>.value.length === 0){ var numWorkingDays = 3; var today = frevvo.currentDate().split('-'); var escDate = calcWorkingDays(new Date(today[0], today[1]-1, today[2]), numWorkingDays); var m = escDate.getMonth() + 1; var d = escDate.getDate(); var y = escDate.getFullYear(); <your date control>.value = m + '-' + d + '-' + y; } |
...
This rule is not yet supported in the Visual Rules Builder and thus still requires some JavaScript. This rule makes sure the end time is at least 4 hours great greater then the start time but no more then 6 hours later then the start time. Also start time must be on or after 1:00. The times must be entered in military units. TS is the name of the Time Start control and TE is the name of the Time End control.
...
Info |
---|
The UserDetail function can also be used to retrieve individual information fields for the currently logged in user. These fields can either be one of the standard fields or a custom attribute configured using the LDAP Security Manager. The standard properties are 'id', 'first.name', 'last.name', 'email' and 'reports.to'. |
...
Code Block |
---|
if (Medrepeat.itemAdded) { var index = Medrepeat.itemIndex; for (var i = 0; i < Medication.value.length; i++) { if (i !== index) { Medication[i].expanded = false; } else { Medication[i].expanded = true; } } } |
Dynamically Setting Min
...
and Max in a Repeat
Imagine an airline reservation form where the number of traveler information sections displayed or the number of rows in a table is based on the number of airline tickets purchased. There is a field in the form for the number of tickets named count and a repeat with a section including controls to collect information about each traveler. You can leave the default values for the Min/Max properties of the Section in the Forms designer or set them to any values provided the min value < max value and the max value > min value.
This is an example of a business rule that displays the number of sections based on the number of purchased airline tickets. Min/Max for the section are set to 1 and 20 in the forms designer.
Code Block | ||
---|---|---|
| ||
var i; if (TravelRepeat.itemAdded) { i = TravelRepeat.itemIndex; TravelNo[i].value = 1 + i; } else { if (count.value > TravelNo.value.length){ TravelRepeat.maxOccurs = count.value; TravelRepeat.minOccurs = count.value; } else { TravelRepeat.minOccurs = count.value; TravelRepeat.maxOccurs = count.value; } for (i=0; i<TravelNo.value.length;i++) { TravelNo[i].value = 1 + i; } } |
...
- The first part of your rule should retrieve the results set (this part of the rule is not shown here). In this example, the user enters a number in the Number of Travelers field in the form.
- The itemAdded statement is needed to determine if you are adding more sections. The first time the rule runs, this statement will evaluate as false and run the else statement
- Evaluate if the number of sections needed is greater than the number or existing sections. If true, set the maxoccurs first because the table needs to increase.
- if the number of sections needed is less than the number of existing sections then set the minoccurs first.
- The rule will loop through the existing sections and set the values in the TravelNo field. If there are still additional sections to be added after the rule has looped through the existing sections, the itemAdded lines will run.
- This rule sets the Min/Max properties to he same values so the plus and minus icons are not visible. This prevents users from adding repeating items.
Entering "5" as the number of travelers, sets the minOccurs and maxOccurs to 5 and shows 5 information sections.
Repeat Item Initialization
...
Each column in a table has a label, help and hint property. These properties work at the column level and can be set dynamically with a rule created with the Visual Rule Builder. Here is an example:
Here is an example of setting the table column printable property using rule code. Line 1 will set the entire column's printable property to false; lines 2-4 show an example of how to make individual cells not printable. Keep in mind that the column setting will override the setting of individual cells.
Code Block | ||
---|---|---|
| ||
Col2.printable = false;
for (var i=0; i<Col2.value.length; i++) {
Col2[i].printable = false;
} |
Show/Hide a Column in a Table
...
If you click on the Rule Code to see the JavaScript generated by the Rule Builder, you will notice:
- The individual rows inside the CustomerTable are referred to in the rule as CustomerTableItem.
- Notice the TableItem deletable property is set to false when a lowercase or 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.
Code Block |
---|
var event = form.load; for (let i = 0; i < ContactCustomer.value.length; i++) { if ((ContactCustomer[i].value === 'Y') || (ContactCustomer[i].value === 'y')) { CustomerTableItem[i].deletable = false; } else { CustomerTableItem[i].deletable = true; } } |
...
Code Block | ||
---|---|---|
| ||
var i; if (TableRepeat.itemAdded) { i = TableRepeat.itemIndex; TravelID[i].value = 1 + i; } else { if (count.value > TravelID.value.length){ Table.maxOccurs = count.value; Table.minOccurs = count.value; } else { Table.minOccurs = count.value; Table.maxOccurs = count.value; } for (i=0; i<TravelID.value.length;i++) { TravelID[i].value = 1 + i; } } |
The images show the table when the user enters 5 as the number of travelers and then changes the value to 3.
Section | ||||
---|---|---|---|---|
|
...
Code Block |
---|
// some VERY likely unique number var n = new Date().valueOf().toString(); PONumber.value = n; new Date().valueOf().toString(); PONumber.value = n; |
Unique Sequential ID
If you are using the frevvo Database Connector and an external database, you can generate unique sequential ids with a database table, a stored procedure and a business rule. Refer to Generate Unique Sequential Id example for the details.
Upload Control
The rules for he Upload Contorl are not yet supported in the Visual Rules Builder and thus still requires some JavaScript.
...
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 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 submission PDF.
Code Block | ||
---|---|---|
| ||
if (u.value.length > 0) { var baseUrl = "/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"/>'; } |
...
The database connector REST services can be invoked via a rule. Refer to the Database Connector chapter for examples of rules using http methods and for configuration details. For an overview of using JSON to dynamically populate dropdown controls click here.
This rule is not yet supported in the Visual Rules Builder and thus still requires some JavaScript.
Show/Hide Controls and Workflow Steps
Often forms/flows need fields that are only used depending on the answers to prior form fields. For example, if your form requires both a Shipping Address and Billing Address but the your form user has checked "Shipping is the same as Billing Address" then it's nice to not clutter the form with the unnecessary Shipping Address input fields. You can use rules to hide the Shipping Address and show it only when the form user says they are different.
The easiest way to create a Show/Hide rule is to use the Visual Rule Builder. Here are common reasons for using Show/Hide:
- Show/Hide a section
- Show a Message to the user to alert them to either an error or success condition
- Show a Details Text Area when as user clicks Yes to "Would you like to describe your issues in detail?"
- Show a Signature or Signed Section when the workflow reaches the approval step.
Show/Hide a Tab on a Workflow Step
See the documentation for Data Sources and Schemas for details on implementing a Show/Hide rule with XSD controls.details. For an overview of using JSON to dynamically populate dropdown controls click here.
This rule is not yet supported in the Visual Rules Builder and thus still requires some JavaScript.