This article is also available in:
Introduction

In Flokzu we know that sometimes it is necessary to provide the forms with intelligence, not only to make complex calculations, but also to validate things, detect errors, and define conditional logic to hide/show fields, among many other possibilities.

Bearing this in mind, we have developed a Script Engine that provides predefined functions at the form level to be able to make all kinds of validations, error detections and algorithms using a widely known language like JavaScript.

Scripts in Flokzu must be defined using the JavaScript programming language, taking advantage of its entire potential. Functions and shortcuts defined in this guide can help you speed up the development of algorithms and conditional logic functions.

Development methodology

The methodology of development for scripts in Flokzu is pretty simple. The logic must be defined within different JavaScript functions and then you must associate those functions to different events (a field changes its value, a button was pressed, etc.) through the use of ‘listeners’ (see below).

The functions defined can make internal use of visibility operations, management of errors or reading/writing of fields, Moment.js or jQuery libraries, among other functionalities.

To make reference to a field in the functions mentioned in this article, you must always write the name of the field between [[ and ]], carefully respecting any upper case and lower case letters, spaces and special characters (e.g. [[Full Name]]).

Lastly, it is necessary to clarify that the ‘listeners’ should not be included when the script is placed inside a calculated ‘script’ field, since there the fields to ‘listen’ are inferred, unlike what happens with task scripts.

Available functions

‘Listeners’

Important: These functions allow to ‘listen’ when a field changes its value (or even when a column from a table changes), and then execute a function that follows a certain logic (e.g. listen when the ‘Passport’ field changes its value to verify that the number is valid).

‘Listen’ to a field
When the listened field changes its value, execute the function.
Flokzu.onChange( [[field]] , FunctionName );

‘Listen’ to a column within a table field
When a certain cell from a column of a table changes its value, execute the function. The field name must be written between [[ and ]], then add "::" and then the column name.
Flokzu.onTableChange( [[field::column]], FunctionName );

Actions
These functions will be executed when the user presses one of the buttons that are available to complete the task. Besides, the function can be defined in such a way that you can identify which was the button that was pressed (see examples of this at the end of this post).
Flokzu.onAction( FunctionName );

Initialize
These functions will be executed when the user opens the process instance and are used to define what will happen in the zero moment. That is, before any field is modified. This applies both to when you are launching a process and to when a user opens a task in his or her tray.
Flokzu.onInit( FunctionName );

Visibility

Important: To be able to modify the visibility of a field by a script, the field must be defined as editable at the process level, that is, in the task where the script is defined, the field must be defined as Editable in the visibility settings tab.

Hide a field
Flokzu.setHidden( [[field]] );

Make a field read only
Flokzu.setReadOnly( [[field]] );

Make a field editable (not required)
Flokzu.setEditable( [[field]] );

Make a field required
Flokzu.setRequired( [[field]] );

Reading/Writing fields

Important: To be able to modify the value of a field using setFieldValue the field must at least be editable at the process level.

Modify a field value (replaces the current value)
This function is valid to all field values, with the exception of: ‘Title / Header’, ‘Table’, ‘Attachment’, ‘Calculated’, ‘Signature’ and ‘Checklist’, which are currently not supported.
Flokzu.setFieldValue( [[field]] , value );

Obtain a field value
This function is valid to all types of fields, with the exception of: ‘Title / Header’ and ‘Table’ which are currently not supported.
Flokzu.getFieldValue( [[field]] );
Special cases according to the type of field:

Yes/No: It returns a boolean (true/false).
Integer number: It returns an integer number or NaN if the field value is not a number.
Decimal: It returns a two-decimals number or NaN if the field value is not a number.
Calculated: It returns a two-decimals number if the field value is a number, no decimals if the number is an integer or else a field value in String format.
Attachment: It returns the name of the attachment or empty if no file was selected.
Multiselect combo box: selected options separated by ‘,’ or empty if there are no options selected.

Iterate the values of a column from a table field
To iterate the values, see the examples given at the end of this post.
Flokzu.getAllColumnValues( [[field::column]] );

Error management

Important: Error management can only be done within the invoked functions from the ‘onAction’. If an error is thrown from a function that is not executed ‘onAction’, it won’t have the desired effect.
By throwing an error from an ‘onAction’, the task is prevented from being completed. The user won’t be able to move forward in the process until he/she modifies the field values in a way that the function does not throw an error in the ‘onAction’.

Throwing an error for a field
The message must describe what happened so that the user can correct the error.
Flokzu.error( [[field]] , ‘message’ );

Others useful functions

Obtain the current user (email)
The email of the user that is currently logged in
Flokzu.currentUser();

Get current Date
Returns the current date, according to the time zone of the account, and the defined date format
Flokzu.getCurrentDate();

Get current Time
Returns the current time, according to the time zone of the account, and in HH:mm:ss format
Flokzu.getCurrentTime();

Get current Date and Time
Returns the current date and time, according to the time zone of the account, and the defined date format
Flokzu.getCurrentDateTime();

Execute column function
It is possible, through our API, to execute the functions and scripts defined in the column of a table. This is useful for example if we want to define default values for a column.
Flokzu.executeTableFunction([[field::column]]);

Obtain the ID of a field from its name
This function is useful in case you are not able/don’t want to use the notation to reference fields ([[ ]]), be it for convenience or because the field won’t be resolved statically at the script level, but it will be resolved in execution time depending on other variables.
Flokzu.getFieldByName( ‘FieldName’ );

Additional libraries

Moment.js
Flokzu incorporates the Moment.js library (https://momentjs.com/) for date/hour management. The included version is the 2.22.2 and it can be used entirely in form scripts for anything related to date calculation. It can be combined with getFieldValue.
Example: moment( [[Time field]] , "HH:mm:ss");

Sweet Alert
Flokzu incorporates the SweetAlert library (https://sweetalert.js.org) to deploy visually attractive popups. The included version is the 1.1.3 and it can be used to point out errors to users at the moment a field changes, without the need to wait for the ‘onAction’ to be executed. Bear in mind that showing an error through SweetAlert won’t prevent the task from being completed.
Example: swal( {type : 'error' , title : 'Error!' , text: 'Error message'} );

jQuery
Flokzu incorporates the jQuery library (https://jquery.com) to perform an endless number of operations/functions. The included version is the 2.2.4 and it can be used for various tasks/shortcuts, like perform Ajax calls.


Examples

Visibility Scripts
Execute ‘onAction’ logic
Get the values from a column in a table field
Validate an Ethereum address and launch a SweetAlert
Subtract two ‘Date’ fields with a Calculated field
Subtract two ‘Time’ fields with a Calculated field
Validate if the value of a ‘Date’ field is prior to the current date
Reduce the number of decimals from a number in a script

TIP: If the arithmetic operation is not working in a desirable way, it is preferable to parse the fields involved using the parseInt and parseFloat functions of JavaScript to make sure that the calculation will be done over correctly defined numbers. Besides, it is preferable to limit the number of decimals with the toFixed function (see example below).

Visibility Scripts

See the post How to set up visibility by script? to understand how to set up those scripts that allow modifying the field visibility, so as to see different examples.

Execute ‘onAction’ logic
Using ‘onAction’, you can define the logic that is going to be executed when any of the buttons used for completing the task is pressed. As we mentioned earlier, it is also possible to determine which button was pressed to perform various operations depending on that.

To evaluate the button that was pressed, the function must receive two parameters. The first one is irrelevant for this example, while the second one is the name of the button that was pressed. In the example below, if the button pressed was ‘Reject’, we’re going to make the field ‘Reason of rejection’ required or else we’re going to hide it.

function validateActions(msg,button){
if(button== ‘Reject’){
Flokzu.setRequired( [[Reason of rejection]] );
}
else{
Flokzu.setHidden( [[Reason of Rejection]] );
}
}

Flokzu.onAction(validateActions);


Iterate the values of a column from a table
In some cases, it is necessary to iterate among the values of a column from a field table if a certain value has been entered and to define a logic following that.

Flokzu’s function ‘Flokzu.getAllColumnValues();’ returns an identifier that then has to be used with jQuery’s ‘each’ function to iterate the elements. Inside the ‘each’ function you need to use ‘$(this).attr('value')’ to obtain the value of the iterated cell.

function iterateTable(msg, data){
$( Flokzu.getAllColumnValues( [[field::column]] ) ).each(
function(){
//Throws an alert with the value.
alert( $(this).attr('value') );
}
);
}

Flokzu.onTableChange( [[field::column]] , iterateTable );


Validate an Ethereum address and launch a SweetAlert
In this example, we will validate the ethereum address entered in a field at the moment that the user enters it, and, in case there is an error, we will show a SweetAlert popup.

For that we are going to use the validation of a pattern with a JavaScript regex to validate the ethereum address, then a SweetAlert in case of error and then, in case that the function is also executed when you are trying to complete a task (sender == evt_ruteo), we will use Flokzu.error to avoid the task from being completed.

Note that on this example we use only one function for both operations, ‘onChange’ and ‘onAction’, and we distinguish internally if it is an action (sender == evt_ruteo) or simply an ‘onChange’.

function ethValidator(sender , button){
if( ! (/^0x[a-fA-F0-9]{40}$/.test( Flokzu.getFieldValue([[Eth address field]])) )){
swal({type : 'error' , title : 'Error!' , text: 'invalid address'});
if(sender == 'evt_ruteo'){
Flokzu.error( [[Eth address field]] , ‘Invalid ETH address’ );
}
}
}

Flokzu.onChange( [[Eth address field]], ethValidator);
Flokzu.onAction(ethValidator);


Subtract two ‘Date’ fields with a Calculated field
With Flokzu it is very easy to create a calculated field that shows the difference (in days) between two date-type fields. To do that we are going to use the Moment.js library that Flokzu has already incorporated.

Step 1
Add 2 Time fields (Example: ‘Date 1’ and ‘Date 2’).

Step 2
Add a calculated field (Example: ‘Subtraction’)

Step 3
Add the script to the calculated field

Script considering only Monday to Friday

calcDiff();
function calcDiff(){
var start = moment( Flokzu.getFieldValue([[Date 1]]) , "YYYY/MM/DD");
var end = moment( Flokzu.getFieldValue([[Date 2]]) , "YYYY/MM/DD");

let weekdayCounter = 0;

while (start <= end) {
if (start.format('ddd') !== 'Sat' && start.format('ddd') !== 'Sun'){
weekdayCounter++; //add 1 to your counter if its not a weekend day
}
start = moment(start, 'YYYY-MM-DD').add(1, 'days'); //increment by one day
}

return weekdayCounter;

}


Script considering consecutive days

calcDiff();
function calcDiff(){
var m1 = moment( Flokzu.getFieldValue([[Date 1]]) , "YYYY/MM/DD");
var m2 = moment( Flokzu.getFieldValue([[Date 2]]) , "YYYY/MM/DD");
return Math.abs(m1.diff(m2, 'days') + 1);
}


Subtracting two Time fields with a Calculated field
With Flokzu it’s very easy to create a calculated field that shows at any given moment the difference (in hours) between two Time fields. For that, we’re going to use the Moment.js library that Flokzu has already incorporated.

Step 1
Add two Time fields (Example: ‘Field 1’ and ‘Field 2’).

Step 2
Add a calculated field (Example: ‘Subtraction’)

Step 3
Add the script to the calculated field

calcDiff();

function calcDiff(){
var m1 = moment( Flokzu.getFieldValue([[Field 1]]) , “HH:mm:ss”);
var m2 = moment( Flokzu.getFieldValue([[Field 2]]), “HH:mm:ss”);

if(m1.isBefore(m2)){
return (moment.utc(m2.diff(m1)).format(“HH:mm:ss”));
}else{
return (moment.utc(m1.diff(m2)).format(“HH:mm:ss”));
}
}


The return of this script has a ‘HH:mm:ss’ format, but this is entirely customizable (Example: ‘HH:mm’ to not show the seconds that went by). For more information, please refer to the Moment.js library
Note that no ‘listener’ was defined since as it is a calculated field, the listeners are inferred by Flokzu’s script engine automatically.

Result



Validate if the value from a ‘Date’ field is prior to the current date

On certain occasions, we want to validate some of the dates we have entered on Flokzu’s Date type fields. In this case, if we want that by pressing a button the system checks if the date entered is prior to the current date and, in case it isn’t, it sends an error and prevents the user from moving forward, the steps would be the following:

Step 1
Add a Date field (Example: ‘Date 1’)

Step 2
Go to visibility settings and then select ‘Scripts’

Step 3
Define the following script in the task you want to use it

function verifyDate(msg, button){

if(button == ‘Name of the button we are interested in’){

// Obtaining the date entered
var dateEntered = moment(Flokzu.getFieldValue( [[Fecha 1]] ) , "YYYY/MM/DD" );

// Obtaining the current date
var currentDate = moment();

// If the date entered is after current date, we launch the error
if(dateEntered.isAfter(currentDatel)){
Flokzu.error([[Date 1]], ‘Here goes the personalized error message’);
}
}
}

//We link the verifyDate function by clicking a button
Flokzu.onAction(verifyDate);


Once this is done, when the user presses the desired button, the script will be executed and, if the date selected is after the current date, and error will be launched and the system will not allow the user to continue.

Reduce the number of decimals from a number in a script

Using a Calculated script-type field, it is possible to make mathematical operations that involve several fields.

For example, if you want to multiply two fields (‘A’ and ‘B’), the script would look like this:

Flokzu.getFieldValue([[A]]) * Flokzu.getFieldValue([[B]])

Even if the script works and it’s a valid one, it’s possible that when you multiply decimal numbers, the result has an infinite number of decimals. To avoid this, you can modify the function as shown below and reduce the number of decimals to three.

( Flokzu.getFieldValue([[A]]) * Flokzu.getFieldValue([[B]]) ).toFixed(3)
Change ‘3’ for the number of decimals that you want.
Was this article helpful?
Thank you!