...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
Panel | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||||||
This chapter contains numerous real world samples of the custom dynamic behaviors you can add to your forms and workflows. Many of the business rules described below are easily created with the frevvo Visual Rule Builder by simply selecting appropriate functions or controls from your forms/workflows using a visual wizard. Rules can still be written with JavaScript in order to build any degree of complex, powerful business logic and integrate with your Web Services and frevvo connectors. |
Navigating this Page
This page is divided into the following sections. Hover your cursor over or click the Table of Contents icon at the top right to browse to a specific section or rule example. To To search the headings and content, type Ctrl-f and enter a keyword.
...
Whether you are using the Visual Rule Builder or editing Rule Code, it is helpful to understand some of the common events that you will use to trigger rules as it they can effect affect the behavior of your forms/workflows. The following examples illustrate the use of form.load, form.unload, form.activate, and form.deactivate events.
...
These two rules together initialize the dropdown fields inside a repeat that are is already in the form via the Form Designer, as well as those added each time a user clicks "+" on the repeat to add a new item & via initial documents. These controls are initialized based on a value set in another field.
...
If this same rule is not marked for initialization, it will be behave like an anytime rule which means that it will fire when the form loads as well as a control value change. The generated JavaScript will include:
...
One common example use is for an order form order number. You may only want to assign a unique sequential order number to each order submission. You could initialize the form's order number when the form loads using form.load. However, if someone start starts filling in the order form but never submitted it you do not want to consume the next order number in sequence if it will never be used. Using form.unload you can assign the number after the submit button click but before the form data is submitted.
Here OrderNum is the name of a invisible control.
Code Block | ||
---|---|---|
| ||
/*member num */ var x; if (form.unload) { eval('x=' + http.get('http://(your webhost)/json/getNextOrdernum')); OrderNum.value = x.num; } |
...
In a desktop browser, users can navigate back and forth between the steps of a screenflow frevvo screenflow or multi-user workflow using the Navigation toolbar. Previous and Next buttons are available on mobile devices for this functionality. Workflow designers should consider this navigation when writing business rules. Steps in a screenflow are read/write since they are all performed by the same user and editing is allowed.
...
Business logic that automatically calculates subtotals, total, and other math functions are is easier for your users and prevent prevents mathematical mistakes. Here are several common examples:
- Expense Report Subtotals and Grand Totals
- Time Sheets Hours per task, per day and per week
- Purchase Order line item costs
Placeholder Formatting (delete before publishing final version)
Condition Wizard
Action Wizard
Else Action Wizard
Rule List
Info | |||||||
---|---|---|---|---|---|---|---|
| |||||||
|
Control Types for Calculations
When using the Visual Rule Builder for calculations, the expressions must have the same value type as the control. For example, math functions are only available on number, quantity, and money controls. If there is a type discrepancy, the VRB Help Mode will display a "Field type mismatch" error:
...
Let's say you have two Number controls which that take a decimal, and you want to set the total in a Quantity control, which only takes a whole number. This rule is valid in the Visual Rule Builder. However, if the user enters values such that the sum is a decimal (such as "2.5"), the rule will set the value as requested, but will truncate the decimal in the total (Quantity) control, showing the value "2" instead of "2.5".
The Visual Rule Builder supports text-to-number conversion with the function number(). For example, you may want to calculate a total from two Text controls that contains contain numbers. Set Total to sum(number(Text1), number(Text2)) to convert the Text control strings to numbers.
...
A common requirement is to set a display a number control with a specific 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 has a table with Number controls for the daily 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. This is JavaScript behavior when calculating decimal point addition. You can use the round() function in the Visual Rule Builder to prevent this and round the Total Hours value to two decimal places.
Action Wizard
The round() function takes two parameters - number and decimal digits. In this example, we're adding several control values to get the number so we enter the addition operation inside parenthesis. The decimal digits parameter is 2.
...
At runtime, notice that Total Hours is now correctly rounded to two decimal places.
Info | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
|
...
The Visual Rule Builder can also handle string concatenation in the function concat(), which takes as many expressions as you want, each separated by a comma. Any literal values used as expressions should be placed inside quotes. For more information, read our documentation on writing rules with strings vs. numbers. In this example, we will create a rule with the Visual Rule Builder to concatenate the First Name and Last Name and display the results in the Fullname field.
Condition Wizard
Action Wizard
Else Action Wizard
Rule List
Info | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
|
...
The easiest way to create a Show/Hide rule is to use the Visual frevvo Visual Rule Builder. Here are common reasons for using Show/Hide:
...
Consider a Purchase Order form that contains a Billing Address section, a hidden Shipping Address section a Radio control named DiffShip that asks the question, "Is the Shipping Address different from the Billing Address?" If the Billing and Shipping addresses are the same there is no need to clutter the form with the unnecessary Shipping Address input fields. You can use a rule to hide the Shipping Address and show it only when the form user says they are different. This rule will automatically fire whenever the user changes the response to DiffShip and will show/hide the shipping address section. In this example, an Else Action is helpful so that when the form loads, and if the user changes a Yes response back to No, the section will be hidden.
...
Action Wizard
Else Action Wizard
Rules List
Info | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
|
...
This rule makes the message control NicknameMsg visible when the user enters a value into the Nickname input text control. It also hides the message control if the user deletes the value in Nickname.
Condition Wizard
This condition makes use of the built-in function "is filled". It will run whenever the control Nickname has data entered in it.
Action Wizard
Else Action Wizard
Rules List
Info | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
|
...
Here's another show/hide example where we are setting multiple conditions to show/hide a message control. This form has a radio control named Facility and a second radio control named CompanyFacility. This rule makes a message control named FacilityMessage visible depending on the selected options. If Boston is selected for the Facility control OR New York is selected for the the CompanyFacility control, the hidden message control will display.
...
Remember to change the "and" to "or" in the Logic expression so the rule will execute if either condition is met.
Action Wizard
Else Action Wizard
...
Expand | ||
---|---|---|
| ||
Show a Tab on a Workflow Step
Tabs are often used like sections to show controls in a grouped view. You may want to display a particular tab only on the relevant workflow step. In this workflow, there is a Tab control with two tabs: Employee and Review. This rule makes the Review tab visible only when the workflow is on the Review step (Step 2).
Condition Wizard
This condition makes use of the built-in condition "current step", which has several options available such as "is", "is on or after", or "is before". The expression field will show a list of available linked steps in your workflow.
Action Wizard
Else Action Wizard
Rule List
Info | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| |||||||||||||||
|
...
You may want to hide the submit and/or cancel buttons on your form under certain conditions. For example, consider a form with multiple tabs. The main tab contains the form and the other tabs contain reference information users may need when completing the form. You only want the submit and cancel buttons visible when the user is in the main tab. This rule hides the submit and cancel buttons when the reference tabs are selected. The control name of the main tab is MainTab. Be sure to select the Main Tab in the designer and then save the form. This ensures the Main Tab will be selected when the form loads and the rule will run.
...
Step 1 has a Section named Manager and a section named Accounts Payable. The Visible property on both these sections is unchecked so they are hidden by default. You want to hide the Manager and Accounts Payable sections for the first step, show the Manager Approval section when the second step is performed by a manager and show the Manager Approval and Accounting sections when the third step is performed by an Accounting department employee.
These two rules will show the Manager Approval section on both the Manager and Accounts Payable step. Note the use of the When current step is on or after Manager condition.
These two rules show the section named Accounts Payable only if the workflow is on the Accounts Payable step. It should not be visible when the workflow is on the steps performed by the employee or the manager.
Info | |||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| |||||||||||||||||
|
...
When the form is submitted we've configured to configured frevvo to send an email with the form PDF. We only want the Details section to appear on the PDF when the user selects 'Yes'. In design mode, uncheck the printable property on the section control. This property will apply to the section and all controls inside the section, so you do not have to uncheck printable on the inner controls. Then create this business rule with the Visual Rule Builder. When the section is visible we also set it to be printable. When the section is hidden we also set it to be not printable.
Info | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||||
|
Enable/Disable Submit and Continue Buttons
A great feature of is frevvo is the fact that a form cannot be submitted or a workflow cannot be continued to the next step until all required fields are filled and all filled fields have valid data (e.g. a date field must contain a valid date). Sometimes it might not be as obvious to the form/workflow user why the form/workflow will not submit or continue to the next step. provides frevvo provides a built-in feature to show validation errors at the time of submission. Refer to the Invalid Form Notification for Users topic to see how it works.
...
There are many times you may want to conditionally enable or disable controls in your form at run time. Let's say you have a form with two controls named Attending and Presenter respectively. Attending is a checkbox with a single option, Yes. If checked, you wish to ask the addition question, Presenter.
Use the Rule Builder to create this rule. This rule will automatically fire whenever the user checks or unchecks Attending and will enable/disable Presenter. In this example, you would typically set the checkbox Attending to be initially unchecked and the radio control Presenter to be initially disabled.
...
Be sure to slide the toggle icon to enter the literal value Yes on the Condition wizard.
Rule List
Info | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
|
...
Oftentimes when you are setting a control's valid property by a business rule, you also want to customize the error message. This can be done in the Visual Rule Builder using the "error message to" function or in JavaScript by accessing the control's status property.
Action Wizard
Info | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
|
...
Rule 1: Set Employee-Only to Optional & Empty if Family is selected. If the user selects family, this rule sets the employee-only radio control to optional and empty. The else action sets the employee-only radio control to required.
Condition Wizard
Action Wizard
Else Action Wizard
Rules List
Rule 2, "Set Family to Optional & Empty if Employee is selected", is similar and is shown in the Rules List below. If the use selects employee-only, this rule sets the family radio control to optional and empty. The else action sets the family radio control to required.
At runtime, both controls are required at first. As soon as one control is filled the other control is set to optional and vice versa. Notice that if you change your selection, the opposite control value is cleared.
Info | |||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| |||||||||||||||||
|
...
You can build forms/workflows in that frevvo that meet Section 508 and WCAG 2.0 accessibility standards. Accessible forms/workflows can assist users with visual and motor impairments. When the Accessible property is enabled for a form/workflow, 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 this special error message. Normally, the status property can be used in a business rule to set (or retrieve) the error message display displayed whenever the control's value is invalid.
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 'm' with the status of the required/invalid control 't', as shown below, the message control will show the Error Message only when an invalid value is entered. It returns a blank value if the required control was left empty.
Code Block | ||||
---|---|---|---|---|
| ||||
if(!t.valid) { m.value = t.status; } |
Similarly, this rule will not display the "You can't leave this empty" message for a required control in a form with Accessibility enabled, because that message is not treated as the control's status. However, the following rule will fill the message control with the literal text specified here (which matches the Accessibiliy message) when the required control is left empty, and the Error Message text if it's filled with an invalid value.
Code Block | ||||
---|---|---|---|---|
| ||||
if (!t.valid) { if (t.value.length === 0) { m.value = "You can't leave this empty."; } else { m.value = t.status; } } |
Dynamic Label, Help or Hint
You can set the value of control labels, help and hint dynamically in a rule. For example imagine you have a form that either volunteers or staff might complete. You'll ask which role they have in the Radio control "Role." Then, dynamically set the label, hint and help messages of the "Name" control to customize it for their role. Create this rule using the Rule Builder. Even though the label of the Name control will look different to the user, the entered data is all present in the same control in the submission.
Rule List
Info | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
|
...
This example form has three sections. The first section is expanded and the 2nd and 3rd are collapsed. When the user fills 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. Use the Rule Builder to create these rules. You will have to create 2 separate rules - one for Step 1 and one for Step2.
Rule List
Info | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
|
...
You might also use this method when a control's pattern has an either/or scenario. In this example, the control should be valid if four numerical digits are entered, or if the word "NONE" is entered in any letter case, e.g. "none" or "None".
Code Block |
---|
var event = form.load; var uc = SSN.value; var res = uc.toUpperCase(); //change text to uppercase to simplify value comparison if (frevvo.step.on('_72odfp6qEeuqr9Bz_J-qDw')){ //if the current step is Step 1 if (res === 'NONE'){ SSN.valid = true; } else if (res !== 'NONE'){ var pattern = /^[0-9]{4}$/g; SSN.valid=uc.match(pattern)?true:false; } } |
...
Let's say you have Number control in your form and you want to display it in a Message control formatted as a money value with commas and decimal places. Add a Number control named Num and a message control named Message to your form. Add a rule and edit the rule code, pasting this rule into the code box. 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 show "$5,600.44".
This rule uses variables to take the value of Num, convert it to a string, split it at the decimal, and add a comma every third digit from the right of the decimal. It then sets the message value to concatenate the dollar sign, the number with commas added, and the decimal.
...
You may want to format money with currency signs, commas, decimals and rounded to two decimal places. This example uses a text control for input and a business rule to format the money value.
This rule declares variables and defines the functions numberWithCommas and formatMoney. numberWithCommas converts the number to a string and adds commas every third digit from the right. formatMoney uses the JavaScript Math object to round the number to two decimal places. The last five lines of this rule take the Amount value, strips special characers the user might have entered, and runs these two functions on them. Then it sets Amount value to concatenate the dollar sign and the newly formatted money value.
...
Here is another example showing a text control named "Money" in a table. Another text control named "Total" displays the column total.
Note the addition of the for loop which runs this rule on each row of the table.
...
Users may enter multi-line text into TextArea controls. If you want to display that text in an html context, for example on a web page, in an html formatted email, or in your form's Form Action display message you will need to replace newlines with html breaks. 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 text control named DF. The user types into the visible control named Description and a business rules converts the newline characters (\n) into html breaks (<br/>), and sets the new value in the hidden control 'DF'. Note that this particular rule also replace the carriage return (\r) with a blank. You will then use the template {DF} in your message control, form action, email, etc.
Code Block |
---|
var x = Description.value; x = x.replace(/\\r/g,""); // replaces "Carriage Return" (CR, ASCII character 13) with a blank x = x.replace(/\\n/g,"<br/>"); // replaces "Line Feed" (LF, ASCII character 10) with an html line break DF.value = x; |
TextArea Wrap Long URL in PDF Snapshot
...
The result places the split values in two separate controls at run time. These controls would typically be hidden in use mode and mapped to the PDF.
Prefilling Rules
Initializing a form with data is a popular way to streamline data entry for your users, declutter forms (prefilled controls can be hidden) and reduce potential errors. Many of these rules optimize built-in methods to retrieve data stored in in frevvo, such as user info, tenant info, and form info.
Tenants, Roles, and Users
has frevvo has several built-in methods that enable you to access information about your current tenant. Some common examples are:
...
Use the Rule Builder to Initialize a form with user data - the Rule Builder has built-in functions for user - information. Use the Dynamic Options feature to populate a ComboBox with a list of users and roles - no JavaScript required.
Displaying lists of roles for selected users and populating Dropdowns with lists of users/roles still require JavaScript using using frevvo built-in methods. Some of these methods return a Boolean true/false value. Others return a JSON string that is automatically converted to a JavaScript object.
...
Prefilling form controls with the logged-in user's info can save your user time and prevent data entry errors. Use the Rule Builder functions userID(), user FirstName(), userLastname(), userFullName(), userEmail(), and userManagerID() to create this rule. When the form loads, fields are populated with the logged-in user information.
Condition Wizard
You don't strictly need a condition for this rule in a form. However, if you are using a workflow, you will want to set a condition to run the rule on the particular step you want to gather user info, or set a condition like "When userID is empty" so that the rule does not run again on subsequent steps that may have different users.
Action Wizard
Rule List
Info | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
|
Info |
---|
Please see this FAQ if you are initializing user data in a workflow with linked steps. |
Populate Form with Any User's Info
Perhaps you want to prefill form fields not with the logged-in user's info, but with another user's info. This might be used in a case where you get the logged-in user's manager's userID, and then you want to look up the manager's email using their userID. In this example, a user id is entered into a text control in the form named UserLookup. When the user enters a user frevvo user id into the UserLookup field, the uFirstName, uLastName, uFullName, uEmail and uManagerID are populated with the information about that user.
Condition Wizard
...
The user functions in the VRB take the parameter userId. In this case, the userId is in the control 'UserLookup', so you enter that control name in each function's parentheses.
Rule List
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'.
Populate Dropdown with Users/Roles
...
Leave the default options for the dropdown controls in the designer.
Code Block | ||||
---|---|---|---|---|
| ||||
if(form.load){ currentTenant.value = frevvo.currentTenant(); currentUser.value = frevvo.currentUser(); AllUsers.options = frevvo.userIds(); AllRoles.options = frevvo.roles(); } |
...
One approach is to populate one dropdown control with all the roles in your tenant, allow the user to choose a role and then display the results in a dropdown. Another approach is to use an invisible text field where you hardcode the role name. Remember that role that frevvo role names are case-sensitive.
Let's say you want to display a list of users that have the Manager role in a dropdown named Role. The user sees only the users that are assigned the Manager role instead of the entire list of users in the tenant. Once a user is selected from the filtered list you can display the details about that user.
Here is an example of a rule that filters the list of users to only those that are assigned the Manager role and populates the options of a dropdown control with the results. The frevvo.userDetails(String userId) function is used to retrieve the details about the selected user (Jim). The results are displayed in a formatted Message Control named m. The form has a text field named Role with an initial value of "Manager". This field is referenced in the rule to supply the role name.
Code Block | ||||
---|---|---|---|---|
| ||||
/*member email, firstName, id, lastName, reportsTo*/ if(form.load){ UsersWithManagerRole.options = frevvo.userIds(Role.value); //Populate dropdown with users who have the role entered in the 'Role' control. } //Display the user details for the selected user var ud = frevvo.userDetails(UsersWithManagerRole.value); m2.value = "<b>Selected User Details :</b><br/>"+ "User ID : "+ud.id+"<br/>"+ "User FirstName : "+ud.firstName+"<br/>"+ "User LastName : "+ud.lastName+"<br/>"+ "User FullName : "+ud.name+"<br/>"+ "User Email : "+ud.email+"<br/>"+ "User ReportsTo : "+ud.reportsTo+"<br/>"; |
...
You can also select more than one role from your tenant list and use a business rule to display a filtered list of users who are assigned any of the selected roles. This business rule populates the options for a checkbox named Roles with the list of all users in the tenant. Selecting more than one role from the list populates a dropdown named UsersWithSelectedRoles with the filtered list of users assigned those roles. Details for the selected user are displayed in a formatted Message Control named m.
Code Block | ||||
---|---|---|---|---|
| ||||
/*member email, firstName, id, lastName, reportsTo*/ if(form.load){ Roles.options = frevvo.roles(); //Populate Checkbox options with all roles in the tenant } UsersWithSelectedRoles.options = frevvo.userIds(Roles.value); //Populate dropdown with users who have any of the roles selected in the Roles checkbox //Display the user details for the selected user var ud = frevvo.userDetails(UsersWithSelectedRoles.value); m.value = "<b>Selected User Details :</b><br/>"+ "User ID : "+ud.id+"<br/>"+ "User FirstName : "+ud.firstName+"<br/>"+ "User LastName : "+ud.lastName+"<br/>"+ "User FullName : "+ud.name+"<br/>"+ "User Email : "+ud.email+"<br/>"+ "User ReportsTo : "+ud.reportsTo+"<br/>"; |
...
It's also possible to list all of the roles assigned to a specified user. This rule gets the user's roles using the same built-in methods we used above to initialize the form with the logged-in user's info. If you were to set them in a text or textArea control, you could simply have added a line to that rule which rule which returns the list of roles.
...
Forms such as invoices, bills of lading, or purchase orders often need to be stamped with a unique ID. There are several different approaches you could take for this business requirement.
- Use the Database the frevvo Database Connector (or another Web Service) to create a sequential unique ID for each submission. See this example in our Database Connector documentation.
- Use the Google the frevvo Google Connector the create sequential numbers. This approach is described in the Google Connector documentation on this page, 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.
If the unique ID does not need to be sequential, you can use the form id generated by frevvo. The _data 'form.id' is guaranteed to be unique for every new form instance. Capture the form id using _date.getParameter as follows:
Code Block title Rule Code: Unique ID using form UUID if (form.load) { InvoiceNum.value = _data.getParameter('form.id'); }
An another approach is create a number from a timestamp using the JavaScript Date method as follows. new Date() creates a date oject object for the exact millisecond the rule runs. Then valueOf() returns the primitive value of that object, and toString() converts it to a string. If it's unlikely you will have multiple forms initialized at the same second, this will very likely provide unique numbers.
Code Block title Rule Code: Unique ID using JS Date() // some VERY likely unique number var event = form.load; if (!(PONumber.value)) { var n = new Date().valueOf().toString(); PONumber.value = n; }
Signatures
offers frevvo offers built-in, legally binding signatures for authenitcated authenticated users. However, there may be times when you want to create your own signature stamp using an external source, pin code, or other such method to authenticate. You may also want to work with the Signature control from palette (anonymous signature) to give it a similar behavior in UI such as setting a date stamp after signing. The following examples demonstrate rules for such scenarios.
...
This form uses a rule to pass a username and password to a an 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.
Code Block | ||
---|---|---|
| ||
/*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=' + u.value + '&password=' + p_encode)); if (x.auth) { var dt = new Date(); var day = dt.getDate(); var month = dt.getMonth() + 1; var year = dt.getFullYear(); d.value = month + '-' + day + '-' + year; d.visible = true; u.enabled = false; p.visible = false; sign.visible = false; m.visible = false; } else { m.visible = 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.
This image shows the case where the doctor entered an invalid PIN and the error message becomes visible.
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.
Set Signed Date
...
Use the today() function in the Rule Builder to create this rule.
Condition Wizard
Action Wizard
Else Action Wizard
Rule List
Info | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
|
...
Finally, use the Visual Rule Builder to concatenate the First Name and Last Name the user entered at run-time.
Rule List
At run time the result looks like this:
...
- To dynamically send an email, add a hidden email control (SendtoCSEmail) to your form.
- In the Email Doc Action (or Email step for a mid-workflow Activity Doc Action), enter the control name as a template in the "To" field.
- Use the Visual Rule Builder to fill the hidden email control with the valid email if the condition is true, and a no-reply email if the condition is false. The Else Action is important here - if you set it to Empty or to an invalid string (any string not using the syntax <name>@<name>.<string>), you will get a submission error.
You can also set the hidden email to a template, as shown below, or to the userEmail() function, so that it is evaluated at run time. - When the user clicks Submit or Continue, the email will send to either the valid email (condition=true) or the noreply email (condition=false.)
...
Tip |
---|
You may want to populate selection control options by pulling from a web service or database. You can do this without writing an JavaScript code with the the frevvo Dynamic Options feature. |
Options
...
Populating options works the same way for all selection controls, by accessing the control's ".options" property. The options must be set in an array, where each value in the array represents an option. The option value is the value passed in the submission .xml document, while the label is what the form user will see. When your option value and label are the same, each array value can simply be the option value. will frevvo will automatically use that item as the option label as well. When the option value and label are different, each array item uses the syntax '<option value>=<option label>'.
...
The run time result will look like this:
Default Selection
...
You can use this business rule to display the Dropdown's option label in a hidden field, and then set that hidden field as the Searchable Field for users to search task list or submissions by. Here's an example of a dropdown where the options value and label are different. Notice that we have a hidden control beside it to collect the selected option's label:
Create a new rule, click Rule Code, and then Edit Rule Code. Add this code (replacing the control names with your control names.)
...
The result is that when an option is selected from the dropdown, we pass the option value in the dropdown control, and the option label in the hidden control. The Selected Option Label control is visible here in use mode for demo purposes:
In the Workflow Settings Searchable Fields tab, select the hidden field (in this example, "Selected Option Label") instead of the dropdown control itself. This allows your users to search by the option label, set in the hidden field, rather than the Dropdown value, which they do not know.
Clear Selections
This sample resets a dropdown option to the automatically added blank option. For dropdowns added from palette controls and from schema, automatically frevvo 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 to 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. This also works for Radio and Checkbox controls, even though they do not have a built in blank option.
Randomize Options
...
You may want the options of a selection control to appear at random each time a user opens the form, such as in a quiz. Add your selection control and options.
Then, add this rule:
...
Each time you load the form, you will see the options in a different, random order.
Tip |
---|
The JavaScript method sort() also allows you to show options in alphabetical order, which can be helpful when getting Dynamic Options from database, Google Sheet, or other web service. |
...
Selection controls' (radios, checkboxes, dropdowns, T/F) options can be set dynamically from a webservice (such as the frevvo Database Connector or Google Connector) via rules. This keeps your forms in sync with your database and ensure the accuracy of your submission data.
Tip |
---|
provides frevvo provides a built-in no-code Dynamic Options feature in the form/workflow designer. See this documentation and short video to see how it works. |
...
This rule is not yet supported in the Visual Rules Builder and thus still requires some JavaScript.
This example uses the Database frevvo Database Connector to set a list products as dropdown options. The option value is the Product Code, which is a rather cryptic number that would not be easy for the user to choose. So, we have set the Product ID as the option value but the user-friendly Product Name as the visible option label.
...
This method is useful when you have multiple ComboBoxes and making multiple calls to the same webservice impacts performance. This simple example gets product data from the Database Connector and stores it in a hidden textArea in the form. Then a second rule parses the data and sets the ComboBox options. Please see the chapter on Reusing Dynamic Content for more details.
...
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 that 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 hidden product ID dropdown. The product choices dropdown control was named Products and the product ID dropdown control was named PID.
...
This rule searches a JSON string (populated from a database, google sheet, or other webservice) and populates a radio control with matching options. The form has a hidden TextArea control, used to save and reuse the JSON string. It also has a text control, trigger, radio control and error message.
- Write a rule to fetch the data from your system and store it in the TextArea, as described here.
Write the following rule to search the stored JSON string and populate the radio control. This rule uses the conditions of a value change in the custName text control OR a trigger click; you only need to choose one of those conditions.
Code Block title Rule Code /*member customers, id*/ var string; var customerlist = JSON.parse(CustomerListJson.value.trim()); if (custName.value.length > 0 || onClick.clicked){ var matchingcustomers = []; var matchtext = custName.value.toLowerCase(); for (var i=0; i<customerlist.customers.length; i++){ if (customerlist.customers[i].name.toLowerCase().indexOf(matchtext) >= 0){ matchingcustomers.push(customerlist.customers[i].id + '=' + customerlist.customers[i].name); } } if (matchingcustomers.length > 0){ SelectCustomer.visible = true; SelectCustomer.printable = true; SelectCustomer.options = matchingcustomers; noMatches.visible = false; } else { noMatches.visible = true; SelectCustomer.visible = false; SelectCustomer.printable = false; } } else { noMatches.visible = false; SelectCustomer.visible = false; SelectCustomer.printable = false; }
The result is a handy search form:
Cascading Dropdowns
...
Dropdowns, Checkboxes and Radio controls can display a Comment field if the user selects the last option. It is most often used as an "Other - please specify" option. In the Forms designer, check the Comment checkbox in the Properties panel and provide a # of rows for the comment area. If the user selects this option, a comment box will appear below asking the user to provide details. Selecting or unselecting the comment property is not supported in rules; however, business rules can be used to set or retrieve the value in the comment field.
Set Comment Field
The Visual Rule Builder can be used to set the comment field to a value or expression.
Action Wizard
Rule List
Retrieve Comment Value
...
Code Block | ||
---|---|---|
| ||
if(Supervisor.commentValue != null){ OtherSupervisor.value = Supervisor.commentValue; } else { OtherSupervisor.value = ""; } |
Tip |
---|
Review this special syntax to reference comment fields in templates. |
...
Code Block |
---|
if(Reason.commentValue){ if(Reason.commentValue.length > 50 && Reason.value){ Reason.valid = false; Reason.status = 'Invalid. Max 50 chars allowed and you have ' + Reason.commentValue.length; } else { Reason.valid = true; } } |
Checkbox Control
...
Let's say you want to list the value of your Checkbox control (the options the user has selected) in another control. This rule has a checkbox control named ColorPalette with the options: purple, green, blue, yellow, orange. The form also contains a text control with name ColorChoice. This rule assigns the choices selected from ColorPalette to ColorChoices. Note that this rule displays the option value, not the option label.
This rule uses a for loop to collect the selected option values in a variable, 'choices'. Then it sets the text control's value to that variable outside of the loop.
...
In this example, the rule displays the labels of the checkboxes the user selects. Imagine the Color Palette checkbox had the options p=purple, g=green, b=blue, y=yellow, o=orange. The above rule would display the values instead of the labels:
In this case the option value and option label are different, and we prefer to display the option label. The rule below loops throught the selected options, and for each selection it finds the corresponding options array item, splits it at the equal sign, and adds the label to the 'choices' variable.
...
The result is that the selected option labels are displayed in the text control.
Checkbox isFilled Condition
...
Using the same form as the example above, this rule changes the Label of the Color Choice control to "Thank You for selecting colors" if options are checked in the Color Palette control. If there are no options checked then the Label of the Color Choice text control is "Please select colors."
Condition Wizard
Action Wizard
Else Action Wizard
Rule List
Info | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
|
...
Info |
---|
When the options of a from-palette checkbox contain spaces, the option array converts each space character to the '_' character. Checkbox controls from schema do not have space replaced with '_'. |
Condition Wizard
Edit the logic expression to "or" instead of "and."
Action Wizard
Else Action Wizard
Notice the addition of the "Set StructureDetails to empty" action, which clears the value if the control is unchecked. This resets the control if a value change is made to the Structures checkbox. For example, the user may have selected one of the Structures checkboxes that made Details visible and entered a value into Details. If the user then changes their mind and unchecks the option that caused Details to become visible, you don't want the value entered into Details to be in your form submission.
Rule List
Info | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
|
...
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 the 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 unchecked again. This is a very common rule design pattern.
This form uses the Compact frevvo Compact layout to align the comment input controls with the checkbox options. Download a working sample that uses JavaScript rules 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; } |
...
Expand | ||
---|---|---|
| ||
Rule List Repeat this rule pattern for each possible checkbox value. |
...
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 workflow 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 < ProgramService.value.length; i++ ){ var v = ProgramService.value[i].replace(/_/g," "); opts[i] = ProgramService[i].value + "=" + v; } SelectedPS.options = opts; var event = form.load; |
Count the Options Selected
...
Code Block | ||
---|---|---|
| ||
Quantity.value = Accessories.value.length + Shoes.value.length + Jewelry.value.length; |
Repeating Checkboxes
...
T/F controls are simplified checkbox controls with only a single visible option.
Tip |
---|
In frevvo versions pre-v10.2, the value property for a Boolean checkbox behaved differently depending on whether it was from schema or from palette. If the T/F control was from schema, you will see For Checkboxes (from schema and from palette) created in v10.2+, the syntax does not require the index. If you use the Rule Builder, this difference will be seamless to the designer. Depending on the frevvo version your T/F control was built in, you may see an index after the control name in the condition, e.g. TaxExemptOrg.value[0]. See Selection Controls for more details. |
T/F Value as Condition
You can use the value of the T/F control as a condition to change the behavior of other controls. Consider a form in which you ask if the organization is tax exempt, and if they are, provide an upload control for the user to attach the relevant documents. Otherwise, leave the upload control hidden. There is a T/F control named TaxExemptOrg and and Upload control named TaxExemptionDocument.
Condition Wizard
Action Wizard
Else Action Wizard
Rule List
Info | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
|
...
You can also set the T/F Value in the Visual Rule Builder. We'll show two examples here - one that sets the value to true, and another that clears the value on a trigger click. Imagine a form with a policy agreement section. Your rule will check "I Agree" for the user (in this example, there is no condition so it sets the value on form.load.) However, you also want the user to have the option to click a button and clear that checkmark if they don't agree.
Action Wizard
Switch the toggle to "literal value" and notice that the VRB gives you a dropdown with the only two possible T/F values, true and false.
Rule List
Info | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
|
...
Now we'll show a rule to clear the value from the T/F control.
Condition Wizard
Action Wizard
There are two possible actions to clear a T/F control: the function 'is empty' which sets the value to null, and the function set 'to' the literal value 'false'. With either action, the result for the user is the control appears unchecked. However, if you have the control's "Required (false)" property checked, there will be a difference in the submission .xml document. Setting the control to null will not show a value in the submission .xml document, but setting the control to false will show the value 'false' in the submission .xml. When the "Required (false) property is unchecked, neither 'to empty' nor 'to false' will show a value in the submission .xml.
Rule List
Info | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| |||||||||||||||
| |||||||||||||||
Tip | |||||||||||||||
In frevvo versions pre-v10.2, the value property for a Boolean checkbox behaved differently depending on whether it was from schema or from palette. If the T/F control was from schema, you will see
|
Date and Time Controls
Excerpt | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
Working with dates and times is very common in most forms. Some common scenarios are:
The samples below show you how to create the most common business logic with dates and times. Working with Date and Time Rules
A Date or Date/Time control can be converted to a js Date object:
A Time field can be converted to a js Date object:
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, however Date/Time controls must have a 2-digit month and day. The rule below can be used to initialize a form with a date and date/time control.
The Date/Time control will display an "Invalid Value" error if single digits for the month and/or day are used .
|
...
Use the today and timeofday functions in the Rule frevvo Rule Builder to populate 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.
Rule List
Use the now function to set your date/time controls to the current date and time in the user's local timezone on formload.
Rule List
Info | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| |||||||||||||||
|
...
This rule sets a control named Signature to the value of a control named Name plus a date/time stamp. The form has a hidden Date and Time field.
Build two rules with the Rule Builder:
- Populate the hidden Date and Time fields with the current Date and Time
Concatenate the text and Date and Time field values
Rule List
Create a Date, Time or DateTime Value
Use the date, time and date/time functions to construct dates and times in your form.
Rule List
Info | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||||
|
...
You can write a rule using the addToDate method to calculate a future date by adding years, months or days to a given date. The example code executes when the form loads. It uses the DateUtil.today() method to populate the control named D1 with the current date. This method returns today's date in the format 'yyyy-mm-dd' instead of 'mm-dd-yyyy', making it compatible with utility with frevvo utility methods such as addToDate(). The rule then
- adds one day to the current date to populate the control named D2.
- adds one month to the current date to populate the control named D3.
- adds one year to the current date to populate the control named D4.
Code Block | ||||
---|---|---|---|---|
| ||||
if (form.load) { var dt = DateUtil.todayISO(); D1.value = dt; D2.value = frevvo.addToDate(dt,'d','1');//add day D3.value = frevvo.addToDate(dt,'m','1');//add month D4.value = frevvo.addToDate(dt,'y','1');//add year } |
...
A common use case for this is to set a deadline, which is then used in a workflow escalation. This form is a Professional Development Request. The user will enter the date of the professional development event. We will calculate a date two weeks past that date as a deadline for them to submit their proof of attendance. In this case we've calculated the deadline in a Date/Time control, so that it can be used in the escalation.
Code Block | ||
---|---|---|
| ||
if (DateOfEvent.value.length > 0) { var dt = DateOfEvent.value; Deadline.value = frevvo.addToDate(dt,'d','14'); } |
Then, you can set up an escalation on the Submit Proof step based on this date. See this documentation for details on how to set up escalations.
Set a Future Date Based on Five-Day Work Week
...
Calculating a date based on a five day work week is a common business scenario used in time sheets and displaying deadlines. You can calculate 'x' number of working days from the current date, and set that date in a Date control on your form. Here is the business rule that will add 3 working days to the current date to give you the deadline 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; } |
...
It can be helpful to display the day of the week (Monday, Tuesday, etc.) on your form based on a specified date. You can do this in a business rule using the getDay() JavaScript method. Here is an example.
Code Block |
---|
var d = new Date(SelectDate.value); var weekday = new Array(7); weekday[0] = "Sunday"; weekday[1] = "Monday"; weekday[2] = "Tuesday"; weekday[3] = "Wednesday"; weekday[4] = "Thursday"; weekday[5] = "Friday"; weekday[6] = "Saturday"; var n = weekday[d.getDay()]; if (SelectDate.value){ DayOfTheWeekOutput.value = n; } |
...
In some cases you may want to display a date in a specific time zone (for example, when scheduling a meeting in a time zone other than the user's time zone). This rule example converts today's date in UTC time zone to Central time zone and adjusts for daylight savings time. The in-line comments in the rule code below explain how this JavaScript works.
Code Block | ||
---|---|---|
| ||
// Converts UTC to either CST or CDT if (form.load) { var today = new Date(); var DST = 1; // If today falls outside DST period, 1 extra hour offset var Central = 5; // Minimum 5 hour offset from UTC // Is it Daylight Savings Time? var yr = today.getFullYear(); // 2nd Sunday in March can't occur after the 14th var dst_start = new Date("March 14, "+yr+" 02:00:00"); // 1st Sunday in November can't occur after the 7th var dst_end = new Date("November 07, "+yr+" 02:00:00"); var day = dst_start.getDay(); // day of week of 14th // Calculate 2nd Sunday in March of this year dst_start.setDate(14-day); day = dst_end.getDay(); // day of the week of 7th // Calculate first Sunday in November of this year dst_end.setDate(7-day); // Does today fall inside of DST period? if (today >= dst_start && today < dst_end) { DST = 0; } // Adjust Date for Central Timezone today.setHours(today.getHours() - Central - DST); var m = today.getMonth() + 1; var d = today.getDate(); var da = today.getDay(); var y = today.getFullYear(); var h = today.getHours(); var min = today.getMinutes(); if (min < 10) { min = '0' + min; } var timezone = ['CDT', 'CST']; var dom = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; var todayStr = dom[da] + ' ' + m + '-' + d + '-' + y + ' ' + h + ':' + min + ' ' + timezone[DST]; DateTime.value = todayStr; //Set the date time string constructed above in a text control DT_C.value = frevvo.dateTime(y, m, d, h, min); //Set the date and time in a DateTime control } |
Duration
offers frevvo offers built-in methods to calculate duration in years (age) or days.
...
It is easy to calculate age with the Visual Rule Builder. This example form automatically determines today's date and then calculates the person's age in the control named 'Age' when they enter their Date of Birth.
Action Wizard
Rule List
Info | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
|
...
- Use the daysBetween function in the Rule Builder to calculate the number of days between the Admission Date and the Discharge Date.
- Populate the Hospital Stay Duration field with the result.
- Concatenate the number of days between the dates with the word "days" in the Hospital Stay Duration field.
- Display an error message in the Hospital Stay Duration field if the Admission Date is later than the Discharge Date.
Rule List
Info | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
|
...
One common use for this function is in a Time Off Request. In this case, you may wish to include both the start and end date in the calculation. Since the daysBetween function counts the start date up to (but not including) the end date simply add +1 in the Visual Rule Builder Expression.
Action Wizard
The result at run time is inclusive of both the start and end dates.
Duration (Working Days)
In some cases, you may want to exclude weekends when calculating the difference between two dates. Here is a rule that let's you calculate just the number of working days:
Code Block | ||||
---|---|---|---|---|
| ||||
function getWorkingDays(startDate, endDate){ var result = 0; var currentDate = startDate; while (currentDate <= endDate) { var weekDay = currentDate.getDay(); if(weekDay !== 0 && weekDay !== 6){ result++; } currentDate.setDate(currentDate.getDate()+1); } return result; } var dt1 = date1.value.split('-'); var dt2 = date2.value.split('-'); var begin = new Date(dt1[0], dt1[1]-1, dt1[2]); var end = new Date(dt2[0], dt2[1]-1, dt2[2]); var days = getWorkingDays(begin, end); NumberOfWorkingDays.value = days; |
...
Code Block | ||
---|---|---|
| ||
var event = form.load; var endDate = null; var startDate = null; var millisDiff = 0; if (StartDateTime.value && EndDateTime.value) { startDate = new Date(StartDateTime.value); endDate = new Date(EndDateTime.value); millisDiff = endDate.getTime() - startDate.getTime(); } var hours = Math.floor(millisDiff / 1000 / 60 / 60); millisDiff -= hours * 1000 * 60 * 60; var minutes = Math.floor(millisDiff / 1000 / 60); Duration.value = (hours <= 9 ? "0" : "") + hours + ":" + (minutes <= 9 ? "0" : "") + minutes; |
Info | |||||
---|---|---|---|---|---|
| |||||
|
...
You may need to calculate the hours difference between two times. This rule makes sure the end time is at least 4 hours greater then the start time but no more then 6 hours later then the start time.
Code Block | ||
---|---|---|
| ||
var event = form.load; var sTime = null; var eTime = null; var millisDiff = 0; if (TS.value && TE.value) { sTime = new Date('1970-01-01T'+TS.value); eTime = new Date('1970-01-01T'+TE.value); millisDiff = eTime.getTime() - sTime.getTime(); if (millisDiff < 4*3600*1000 || millisDiff > 6*3600*1000) { TE.valid = false; } else { TE.valid = true; } } |
...
Simple Time Between - this rule finds the difference between two time controls in the form, and displays the difference in hh:mm format.
Code Block language js title Rule Code - Simple Time Between var event = form.load; var endDate = null; var startDate = null; var millisDiff = 0; var sd = Date.value + 'T'+ FromTime_c.value + 'Z'; var ed = Date.value + 'T'+ EndTime_c.value + 'Z'; if (FromTime_c.value && EndTime_c.value) { startDate = new Date(sd); endDate = new Date(ed); millisDiff = endDate.getTime() - startDate.getTime(); var hours = Math.floor(millisDiff / 1000 / 60 / 60); millisDiff -= hours * 1000 * 60 * 60; var minutes = Math.floor(millisDiff / 1000 / 60); TimeBetween_c.value = (hours < 9 ? "0" : "") + hours + ":" + (minutes < 9 ? "0" : "") + minutes; } else { TimeBetween_c.value = null; }
Time Sheet Table - this example has a table where a user can enter multiple From and To times. The rule finds the hours and minutes between, stores them in hidden table columns and displays the result for each row in the format "# hours # minutes".
Code Block language js title Rule Code - Time Sheet Table var event = form.load; var endDate = null; var startDate = null; var millisDiff = 0; for (var i = 0; i < FromTime.value.length; i ++){ if (FromTime[i].value.length > 0 && EndTime[i].value.length > 0) { var sd = DateEnter[i].value + 'T'+ FromTime[i].value + 'Z'; var ed = DateEnter[i].value + 'T'+ EndTime[i].value + 'Z'; startDate = new Date(sd); endDate = new Date(ed); millisDiff = endDate.getTime() - startDate.getTime(); var hours = Math.floor(millisDiff / 1000 / 60 / 60); millisDiff -= hours * 1000 * 60 * 60; var minutes = Math.floor(millisDiff / 1000 / 60); timeBetween[i].value = (hours < 9 ? "0" : "") + hours + " hours " + (minutes < 9 ? "0" : "") + minutes + ' minutes'; Minutes[i].value = Number(hours) * 60 + Number(minutes); } else { timeBetween[i].value = null; } }
We can also display the total time for the entire table in a "total time" control. This can be displayed as a number by using the Visual Rule Builder to sum the Minutes column, divide by 60 to get a decimal representation of the total hours, and then rounding to two decimal places.
Commonly in a Time Sheet use case, you will want to round the time to the nearest quarter-hour. Here is a JavaScript rule that does just that.Code Block language js title Rule Code: Total Time to Nearest Quarter Hour var sum_result; var event = Table6Repeat.itemRemoved || Table6Repeat.itemAdded || form.load; sum_result = 0; for (let i = 0; i < Minutes.value.length; i++) { sum_result += Minutes[i].value; } var number = (sum_result / 60); totalTime.value = number = (Math.round(number * 4) / 4).toFixed(2);
...
- Uses the is after condition for the Date of Birth control
- Sets the Date of Birth status to invalid if the entered date is after the current date
- Sets the error text for the Date of Birth field to "Birth Date must be earlier than today"
Rule List
Info | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
|
...
- A rule that uses the daysBetween function to calculate the number of days between the AppointmentDate and the current date. See the Duration rule example for how it works.
- A rule that sets the invalid property and error text of AppointmentDate if there are more than 14 days between the two dates.
Rule List
Date No More Than x Days Ago
...
The form contains a hidden field named DaysAgo (visible here for demo purposes).
You will need two rules created in the Rule Builder:
- A rule that uses the daysBetween function to calculate the number of days between the Event Start Date and the current date. See the Duration rule example for how it works.
- A rule that sets the invalid property and error text of Event Start Date if the date entered is more than 30 days before the current date.
Rule List
Show Error Message if Date1 is On or Before Date2
You are designing a weekly Time Sheet that has fields where the user must enter the From and To dates for the reporting period. If the date entered in Period To is equal to or earlier than the date entered in Period From field, you want to show this error message "Must be after From Date".
Condition Wizard
Action Wizard
Rule List
Info | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
|
...
This rule is not yet supported in the Visual Rules Builder and thus still requires some JavaScript.
The server frevvo server stores all date control values in a canonical yyyy-dd-mm format, irrespective of your date control's Date Format property. The Date Format you set in the designer affects only the format the user sees at run time and not the actual stored value. The canonical format is also what you will see in your form's submission XML. When you want to use a date control's value in a message control you will need to convert the canonical date format to your desired display format. This rule writes the date control named 'datefield' into a message control named 'Msg' using the format dd/mm/yyyy.
...
The date control can be set to either just a date, just a time, or a combined date/time. Using the Rule Builder you can copy values from these fields to other controls in your forms/workflows.
Rule List
Info | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
|
...
Here is an example of a business rule created using the Visual Rule Builder, that makes a field in a repeat control "Age" visible and required when another field in that repeat, "Name" is filled in.
Rule List
Info | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| |||||||||||||||
|
...
The event handler itemAdded is a useful condition for repeats and tables, as it runs the rule or statement whenever a new item is added to a repeat. Imagine your form has a Repeat named Erepeat that contains a section named Employee. The Employee section control contains many controls such as Name, Phone, Email, a dropdown for Manager, and a radio control for Shift.
will frevvo will execute this rule each time a user clicks "+" on the repeat to add a new item. Here we want to default Shift to the value 'Day', and populate the Manager dropdown dynamically with values from the Database the frevvo Database Connector. Usually, your form will have a form.load rule to initialize dropdown options for the first repeat item visible on your form by default.
...
Info |
---|
The same rule can be written for a table control. The name of a table's repeat is always <TableName>Repeat. For example, if you name your table Children, the repeat is named ChildrenRepeat. |
...
This rule executes when a new item is added to a repeat. This form contains a repeating section with a templatized label. It is nice to collapse the other items when adding a new item to keep the repeat list small and grid-like. Medrepeat is the name of the repeat control. Medication is the name of the section control inside the repeat.
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; } } } |
...
You can use a business rule to set a Repeat or Table's min and max properties based on data entered at run time. Imagine an airline reservation form where the number of traveler information sections/rows displayed is based on the number of travelers. This example form has a field labeled Number of Travelers, named 'count', and a repeat named 'TravelRepeat' with a Traveler Info section. 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 business rule displays numbered sections based on the number of travelers.
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; } } |
...
Info | ||
---|---|---|
| ||
|
Entering "3" as the number of travelers, sets the minOccurs and maxOccurs to 3 and shows three (3) information sections.
Repeat Item Initialization
...
Note |
---|
itemAdded and itemIndex are properties of the Repeat control. |
Code Block | ||
---|---|---|
| ||
if (RepeatTrack.itemAdded) { var index = RepeatTrack.itemIndex; albumOnly[index].value = 0; } |
...
The itemAdded event also executes when adds when frevvo adds items found in an init doc. Consider a case where you only want to initialize items added when the user clicks "+" on the form, not those added from an initialization document. An example is a form that contains a Mailing Label section in a Repeat named 'MLrepeat'. Each label needs a unique ID assigned in a control named 'MLmid'. We plan to initialize this form from a database, where these IDs are already saved, so we only need to assign new IDs when the user manually adds a new Mailing Label by clicking the "+" button on the form. When the form is submitted the assigned IDs are saved in the database via the form's Doc URI, so the next time it runs it will pull back the newly added rows and their IDs as well.
...
You can easily auto populate incremental items numbers in repeats using a business rule. In this example Erepeat is the name of the repeat control and Item is the name of the item control inside the repeat. You also need to set 1 as the default value of first repeating Item control directly into your form field via the form designer as shown here.
Code Block | ||
---|---|---|
| ||
if (Erepeat.itemAdded || Erepeat.itemRemoved){ for(var i = 0; i < Item.value.length; i++) { Item[i].value = i+1; } } |
Tables
Table controls are often used in formsfrevvo forms/workflows. Tables are used in many situations. Here are just a few:
...
The Visual Rule Builder supports the calculation of SubTotals CalculateaSubtotal and Grand Totals CalculateaGrandTotal, showing/hiding Table columns, and hiding the Minus icon. The rest of the business rules in this section are not yet supported in the Visual Rule Builder and thus still require some JavaScript.
...
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.
Rule List
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.
...
The Visible property is available on the column level and can be used in a rule to make the whole column visible or hidden. For example, let's say you have a table with 3 columns in a two step workflow. You want all three columns to display for Step 1 of the workflow. When the workflow navigates to Step 2, you do not want the ID column to display.
In the designer, the visible property is checked on the ID column property panel.
Here is the rule created with the Rule Builder that hides the ID column on Step 2.
Rule List
The Visible property is available on each table cell as well and can be used to make the cell content visible/invisible. Here is a rule that will hide the cell contents of the first cell in column a:
Code Block | ||
---|---|---|
| ||
if(form.load) { a[0].visible = false; } |
Hide the Minus Icon on a Table Row
...
The easiest way to create a rule like this is to use the Rule Builder. Let's take a look at a simple example. Users are instructed to enter a lower case or capital Y in a table if they are planning on calling a customer. The user enters the "Y" or "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 the first column in the table is named ContactYN.
Condition Wizard
Change the Logic Expression from "and" to "or".
Action Wizard
Use the deletable/non-deletable properties in the Action and Else Action wizards.
Else Action Wizard
Rule List
Info | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
|
...
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.
Note |
---|
When you change the minOccurs and maxOccurs values in a business rule at run time, and the rule sets the min and max to the same value, the plus and minus icons disappear but the empty left-side column will still display. |
...
At runtime, the form looks like this:
Clear Values in a Table
Use the Rule Builder to create this rule which clears the values from all rows in a table. Simply set the name of your table control to empty. In the rule shown, the Table control named MyTable is cleared when a trigger (ClearTable) is clicked.
Rule List
Info | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
|
...
In most cases, the Link control can be used to add a clickable link to your form that can also be clicked from the submission PDF snapshot. However, Link controls cannot be added to tables. Instead, use a message control with a rule like this to seamlessly show the clickable link on the PDF printout. For example, on an office supply order form you want the user to add the link to the requested product. The PDF snapshot will go to the buyer, who only needs to click the link. In this example, the message column is hidden in use mode and only appears on the PDF snapshot.
Code Block | ||
---|---|---|
| ||
for(var i=0; i < Link.value.length; i++){ if(EnterLink.value){ Link[i].value = "<a href='" + EnterLink[i].value.split('?')[0] + '?' + encodeURIComponent(EnterLink[i].value.split('?')[1]) + "' target='_blank'>Open</a>"; } else{ Link[i].value = null; } } |
...
Perhaps you need a simple rule to calculate the number of rows (in this case, Items) in a table. This table has a column named Item and a separate quantity control named NumberOfItems. We can use the Visual Rule Builders countIf function to count how many rows have a value in the Item column. The countIf function takes two arguments - first, the control to be counted, and second the condition on which to count it. In this case, we are using the isFilled function inside the second argument.
Action Wizard
The result is that the quantity field Number of Items automatically displays the number of rows in which the Item column is filled.
Info | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
|
...
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 frevvo 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"/>'; } |
Here is the example form before and after the user has upload uploaded the frevvo_logo_small.png image:
This rule is a bit more complex to handle the case where the user uploaded multiple images via the upload control.
...
You can use a business rule to capture the total number of uploaded files at run time.
Code Block | ||||
---|---|---|---|---|
| ||||
if(Upload.value[0] === "_"){ //Looks at the first index to see if only a single file is uploaded FileCount.value = 1; } else { FileCount.value = Upload.value.length; } |
...
Tip | |||||
---|---|---|---|---|---|
| |||||
Use this method to:
|
In this example, we simply change the value of a text control based on another control in them form. The Message uses templates to display the text control.
Form Designer
Run Time
Rule List
However, you may wish to use JavaScript for more complex rules, switch cases, or even just to improve readability of the rule. Here's an example from the Expense Report by Category prebuilt template. This rule calculates a subtotal for each category selected and displays it in a message control.
Code Block | ||
---|---|---|
| ||
/* We won't use the Visual Builder here since we want to format the message for end user readability */ var cats = []; for (var i = 0; i < Amount.value.length; i++) { if (Status[i].value === 'Ok') { if (cats[Category[i].value]) { cats[Category[i].value] += Amount[i].value; } else { cats[Category[i].value] = Amount[i].value; } } } var s= "<strong>Expenses by Category:</strong><br/><table cellspacing='8'><tbody>"; for (var i in cats) { if (i) { s += '<tr><td>' + i + '</td><td>' + cats[i].toFixed(2) + '</td></tr>'; } } s += '</tbody></table>'; CatExp.value = s; if (ExpenseRepeat.itemRemoved) {var x;} |
Here's another example that displays data from a repeat control in a message control as an HTML table.
Code Block | ||||
---|---|---|---|---|
| ||||
var Name_start_index = ContactsRepeat.itemAdded ? ContactsRepeat.itemIndex : 0; var Name_end_index = ContactsRepeat.itemAdded ? Name_start_index + 1 : Name.value.length; var event = form.load; //set the initial value of t to the table headers var t = '<strong>Contact Information:</strong><br/><br/><table style="width:50%" border="1px solid black"><tr><th>Name</th><th>Email</th></tr>'; //for each repeat instance, add to t a new html table row with the corresponding repeat data for (let i = Name_start_index; i < Name_end_index; i++) { if (Boolean(Name[i].value)) { t += '<tr><td>' + Name[i].value + '</td><td>' + Email[i].value + '</td></tr>'; } } //Finally set the value of the message control the string constructed above plus the table end tag ContactsMessage.value = t + '</table>'; |
...
- Upload your PDF to a location on your website, and copy the link for it.
- Add a Message Control to your form. Give it a name (in this example we use the name PDFStatic and set the Message Type to "None."
Add a Business Rule like this:
Code Block title Rule Code if (form.load) { var baseUrl = "https://s3.amazonaws.com/static.frevvo.com/docs/Sample+PDF.pdf"; PDFStatic.value = '<iframe width="100%" height="750" src="' + baseUrl + '" frameborder="0" ></iframe>'; }
- Set the variable baseUrl to the link for your PDF.
- Then, set your Message Control to a string including the iframe tags and the base url.
- Save and Test the form. The PDF controls at the top may vary based on the user's browser, but in most cases allow the user to download or print the PDF, and to scroll up and down the PDF if it is multiple page.
Method 2 Upload the PDF in frevvo's PDF Mapping tool
...
- In order to upload a PDF into frevvo's PDF Mapper, it must be an acroform. Start by uploading it to a tool like PDF Escape. If you plan to map fields, you can set the fillable fields in that tool. If you only need to display it, simply upload the PDF to that tool, add a Form Field anywhere on the document (it will not be visible to the user), then immediately download it again as a fillable acroform.
- Open your form and select PDF Mapping in the Guided Designer navigation bar.
- Click the Add icon and upload your acroform.
- Return to Forms editing mode by clicking Form(s) in the Guided Designer navigation bar.
- Add a Message Control to your form. Give it a name (in this example we use the name PDFfrevvo) and set the Message Type to "None."
- Add a Form Viewer control to your form. In the From property, choose the form you just uploaded.
- Save and test the form, and click the Form View control. The PDF will open in a new tab. Click on the URL and copy from /genform/... to the end of the url. Paste to a text pad - we'll use this in our business rule.
- Optionally, set the Form Viewer control to hidden. Once you have the URL, you do not necessarily need this control visible to users.
Add a business rule like this:
Code Block title Rule Code if (form.load) { var baseUrl = "/frevvo/web/tn/" + _data.getParameter('tn.id') + "/user/"+_data.getParameter('user.id') + "/app/"+_data.getParameter('app.id') + "/form/"+_data.getParameter('form.id'); PDFfrevvo.value = '<iframe width="100%" height="750" src="' + baseUrl + '/genform/_dMOPwEFOEeurl6p3Z49rvQ?action=gen-form' + '" frameborder="0" ></iframe>'; }
- Set the variable baseUrl to construct your form's URL. This is dynamic, so if you later move a form from a development tenant into a production tenant, the url will contineu to work. If you are setting this rule in a workflow, be sure to use /flow/ and 'flow.id' in place of /form/ and 'form.id'.
- Set the message control to a string that includes the iframe tags, the baseUrl, and the /genform/... url parameter you copied in Step 7.
- Save and Test the form. The PDF controls at the top may vary based on the user's browser, but in most cases allow the user to download or print the PDF, and to scroll up and down the PDF if it is multiple page.
Display PDF with mapped fields
...
- Get the URL for your video, such as a YouTube link.
- Add a Message Control to your form. Give it a name (in this example we use the name VideoMsg) and set the Message Type to "None."
Add a Business Rule like this:
Code Block title Rule Code if (form.load) { VideoMsg.value = '<iframe width="100%" height="450" src="https://youtube.com/embed/AOtLYy6I9Vg" + " frameborder="0" ></iframe>'; }
This rule sets the Message Control to a string that includes the iframe tags and your video link.
- Save and Test the form. Your users can play the video right in your form.
Rules for Integration
...
In many cases, integration with your database via the Database the frevvo Database Connector can be accomplished with the Doc URI approach and/or the dynamic options feature, without the need for complex business rules. However, if you wish to use business rules, there are rules on this page that handle database integration.
...
This rule is not yet supported in the Visual Rules Builder and thus still requires some JavaScript. Rules can be used to save a snapshot of location information of any form. For example, an insurance company may want to capture the GPS location of their representatives filling out a form used for audit purposes. The designer can use the frevvo Geo Location feature in conjunction with rules like the ones shown in the examples below to accomplish this. When the form loads in the browser, the user will be prompted by to allow/disallow the use of location services. If permission is granted, the position will be calculated and server will be updated via an Ajax which causes the rule to fire. If the user denies permission or there is a timeout, the server will get an Ajax with an error.
...
Here is an example of a location tab on a Police Report form.
Checking the Detailed Loc checkbox in the Form Property pane and implementing a rule like the one shown will go to Google Maps to get additional information and a map associated with the location.
...
- Get a Google Maps API Key.
Create a form with "From" and "To" Dropdown controls as well as controls to calculate mileage as in this example.
Expand title Click here to see example form... The dropdown option addresses must have a "+" between each word and no special characters, and should include a city and state abbreviation at a minimum. Zip code is not needed. Format the left-side values as follows:
Code Block title Rule Code //Format StreetNumber+StreetName+City+StateInit=Label //Examples 123+Peach+Ln+Anytown+CT=Anytown, CT Chicago+IL=Chicago New+York+NY=New York, NY
Note the the label (right-side value) can be any value you want your users to see in the dropdown list.Create a business rule to calculate the mileage.
Code Block title Rule Code /*member distance, rows*/ var x; var origins = ""; var destinations = ""; var total = 0.0; for (var i = 0 ; i < From.value.length; i++) { if (From[i].value.length > 0 && To[i].value.length > 0) { origins+=From[i].value + "|"; destinations+=To[i].value + "|"; } } if (origins.length > 0) { eval('x=' + http.get('https://maps.googleapis.com/maps/api/distancematrix/json?origins=' + origins + '&destinations=' + destinations + '&units=imperial&key=<Your Key>')); var miles; for (var i = 0 ; i < x.rows.length; i++) { miles = Math.round(x.rows[i].elements[i].distance['value']*0.00062137); total += miles; Miles[i].value = miles; } TotalMilesClaimed.value = total; Amount.value = total * IRSMileageRate.value; } if (MileageTableRepeat.itemRemoved) {var x1;}
The form will automatically calculate the mileage between locations, multiply it by the IRS Mileage Rate, and calculate the total reimbursement.
Search Popup
This rule is not yet supported in the Visual Rules Builder and thus still requires some JavaScript. frevvo forms can initialize dynamically from backend systems. A common form design pattern is the master/detail. An example of master/detail is a form that contains an order number or employee Id. When the user enters an existing Id into the form field you want all other form fields to populate dynamically from values in a database. This is done using a form created from XSD data source generated by the database connector. This part of the master/detail form design pattern needs no business rule. It happens automatically using the Doc Action manually set document URIs. See the DB Connector Tutorial for complete detail on how to initialize your form using a Doc Action document URI to your database.
This form was created from employee.xsd generated by the database frevvo database connector. The master Id is a control from that XSD named racfid. The key to this design pattern is in using the master Id in the form's doc action document URI. In this example the form's doc action document URI for the employee document is set to:http://localhost:8082/database/myqset/employee?racfid={racfid}.
...
If you know the RACF ID for an employee you can simply type it into that field. If the RACF ID is found in the database the form will automatically populate all other fields from the database (because of the doc action document uri setting). However, if you do not know the employee's RACF ID you can click the Find Employee trigger.
...
The section control contains controls that are the search criteria for finding a RACF ID based on other pieces of information you may know about an employee such as name, type, and email address. The values entered into the search criteria can be partial values. For instance, entering a the 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".
...