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 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. To search the headings and content, type Ctrl-f and enter a keyword.
Rule Events
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 can effect the behavior of your forms/workflows. The following examples illustrate the use of form.load, form.unload, form.activate, and form.deactivate events.
...
The examples in this section are organized by the rule's business function, i.e. calculations/mathematical rules, show/hide rules, and rules for various control properties.
Calculations 1069155763 | Show/Hide Rules | Control Property Rules | Formatting Rules | Prefilling Rules | Doc Action, Activity Doc Action, and Precondition-Related Rules
Calculations
Business logic that automatically calculates subtotals, total, and other math functions are easier for your users and prevent mathematical mistakes. Here are several common examples:
...
Note |
---|
The sum() function mentioned above will calculate over the entire repeat/table. To use addition to subtotal individual rows, use the "+" operator, i.e. Set Subtotal to Item1 + Item2. |
...
Consider a Purchase Order form with a table that calculates subtotals as described above. Now you want to add a Grand Total field to your Purchase Order workflow. The Grand Total field contains the sum of the Subtotal fields in each row of the table. Add a Money control to your form/workflow and name it Grand Total. Use the Rule Builder to create the rule. The Rule Builder automatically creates the code to handle adding/deleting table rows.
...
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
...
You can build forms/workflows in 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 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.
...
Info |
---|
This rule is similar to the format money rule above, in that it adds a decimal with two zeroes behind the number entered, so 12345 displays as 12.345,00. If you'd rather convert the number to a decimal as entered, simply remove the '* 100' from the Math.round() method parameters. This change will display 12345 as 123,45. |
...
A common requirement is to filter the list of users in a tenant to display only users that have a specified role. The frevvo.userIds() and frevvo.roles() functions can be used in a rule to accomplish this.
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 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.
...
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 returns the list of roles.
...
This section will cover example rules for various control types. Some control types have their own properties and methods, which are helpful to understand when using the Visual Rule Builder or Rule Code Editor to customize their behavior.
Selection Controls | Date and Time Controls | Repeats 1069155763 | Tables 1069155763 | Upload Control | Message Control
Selection Controls
Dropdowns, Checkboxes, Radio, ComboBox and T/F controls are selection controls. You can populate your selection control options, either statically or dynamically, using business rules. You may want such customized picklists for:
...
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. |
...
Example 3 - Populate Options from JSON
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 frevvo 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.
Note |
---|
The "Single Value" property must be checked in order for this to work properly. |
Code Block | ||
---|---|---|
| ||
if (form.load) { JSONData.value = http.get('http://localhost:8082/database/combobox/allproductsByName'); } |
...
Code Block | ||
---|---|---|
| ||
/*member productName, resultSet*/ if (ComboBox.matchText) { var opts = []; var j = 0; var x = JSON.parse(JSONData.value); for (var i = 0; i < x.resultSet.length; i++) { if (x.resultSet[i] && x.resultSet[i].productName.toLowerCase().includes(ComboBox.value.toLowerCase(), 0)) { opts[j] = x.resultSet[i].productName; j++; } } ComboBox.matchingOptions = opts; } |
Note that this example removes case sensitivity using the toLowerCase() function on both sides of the comparison.
You may use the includes() function or the startsWith() function. includes() will return true if the string contains the specified string (in any position), where startsWith returns true if a string starts with a specified string. includes() will tend to produce more results; the method you choose will depend on your data and how your users tend to use typeahead.
Example 4 - Populate ComboBox in a Table
Similare Similar to Example 3, this reuses content stored in a hidden text control in your form. However, it provides additional code to loop through the table when setting options.
...
Warning |
---|
The method shown here is an older way of providing a user with friendly options while also passing a more cyrptic value, such as a unique id used in database tables, to the submissions document. In many cases you will find the example above, Populate Options from a Database, which dynamically sets <option value>=<option label> to be a more straightforward solution. |
...
The second rule is covered below in Find a Selected Options Index.
Here is another rule that dynamically populates both the product choices and product ID dropdowns. This rule calls a REST Service which returns an object rather than the resultset returned by the database connector as shown above. See the section on dynamic content for more details.
...
This rule dynamically sets the options in a dropdown list based on the value selected in another dropdown, creating an effect of "cascading" dropdowns. This form contains three fields named Products, Series and Model. The series options are set dynamically based on the product selection, and the model options are set based on the series selection. When a new product is selected we enable the series dropdown and both clear and disable the model dropdown. For this example, we have hard coded the option arrays; however, you could replace those with dynamic options (i.e. options from a database) using the prior selection in the query URL. See the Database Connector Tutorial for an example.
...
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; |
...
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 .
|
...
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; } |
...
- A rule that uses the daysBetween function to calculate the number of days between the AppointmentDate and the current date. See the Duration 1069155763 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.
...
- 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 1069155763 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.
...
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
...
The Visual Rule Builder supports the calculation of Subtotals and GrandTotals, 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.
Tables are a grid layout of repeating items, and so they are identical to repeat controls when referenced in business rules. All the rule examples in this chapter that discuss repeats apply also to tables. The one important note is that you cannot explicitly name the repeat control inside your table. The repeat control inside a table is automatically named as <TableName>Repeat. For example a table named Expense automatically has a repeat named ExpenseRepeat. The rule ExpenseRepeat.itemAdded and ExpenseRepeat.itemIndex references an item added to your table and that item's index respectively.
...
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. |
...
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 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"/>'; } |
...
- 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.
...
In many cases, integration with your database via 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.
Additional details and rule examples for database integration can be found in the Database Connector Tutorial.
...
REST web services can be invoked via a rule. The frevvo database connector is a practical example of a REST web service. Refer to the Database Connector Tutorial for examples of rules using http methods. REST web services very commonly return JSON strings. For an overview of how to parse JSON in a business rule, for example to populate dropdown controls, see our rule example for Dropdown Options and also our documentation on Reusing Dynamic Content.
...