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.
...
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.
...
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.
...
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; } |
...
Info | ||
---|---|---|
| ||
The function "calcWorkingDays" in this rule takes two parameters, fromDate and days, which you set in the if statement. This function increments the from date by 1 day at a time until it reaches the number days you specified. uses the getDay() method, which returns the day of the week (from 0 to 6) for the specified date. Sunday is 0, Monday is 1, and so on. It increments the date as long as the day of the week is not '0' (Sunday) and '6' (Saturday). The if statement runs on form.load and when your date control is empty. This ensures it does not overwrite the original deadline on later workflow steps. Then it gets the current date and splits it into an array (day of the week, month, day of the month) which the function can handle. It runs the calcWorkingDays function using this array as the fromDate parameter, and the numWorkingDays variable as the days parameter. Then the rule uses the getMonth(), getDate(), and getFullYear() methods to parse the result back into date format so you can set it as the date control's value. You may notice that when using getMonth() we add one to the result - this is because the month is returned as it's array position, so January is 0, February is 1, and so on. By adding 1 we get the month number that our date control expects, January is 1, February is 2, etc. |
Similarly, you can calculate a future date that accounts for both weekends and specific holidays. In this example, you will specify holidays in the holiday array. Then, the isHoliday and compare functions check each date in the count to see if they are weekends or a holiday.
Code Block | ||||
---|---|---|---|---|
| ||||
var holiday = [];
holiday[0] = new Date(2023, 2, 2);// holiday 1
holiday[1] = new Date(2023, 2, 3);// holiday 2
function calcWorkingDays(fromDate, days) {
var count = 0;
while (count < days) {
fromDate.setDate(fromDate.getDate() + 1);
if (fromDate.getDay() !== 0 && fromDate.getDay() !== 6 && !isHoliday(fromDate, holiday)) { // Skip weekends
count++;
}
}
return fromDate;
}
function isHoliday(dt, arr){
var bln = false;
for (var i = 0; i < arr.length; i++) {
if (compare(dt, arr[i])) { //If days are not holidays
bln = true;
break;
}
}
return bln;
}
function compare(dt1, dt2){
frevvo.log(dt1, dt1);
var equal = false;
if(dt1.getDate() == dt2.getDate() && dt1.getMonth() == (dt2.getMonth()-1) && dt1.getFullYear() == dt2.getFullYear()) {
equal = true;
}
return equal;
}
if (form.load && DeadlineSkipW.value.length === 0){
var numWorkingDays = 10;
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();
DeadlineSkipWH.value = m + '-' + d + '-' + y;
} |
Here, we have three rules; one sets the deadline to 10 days in the future, one sets the deadline skipping weekends, and one skips both weekends and holidays. We ran the form on Jan 31, 2023 and set our holidays as Feb 2 and Feb 3, 2023.
Get Day of Week from 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
...
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"/>'; } |
...