Script development in Flokzu
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’ );
Other useful functions
Obtain the current user (email)
The email of the user that is currently logged in
Flokzu.currentUser();
Get the current assignees
Returns the name and email of the users or the roles that are assigned to the task
Flokzu.getCurrentAssignees();
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’ );
Change the size of the columns
In case you want to modify the size of the columns of a table, you must use the following script.
The sum of all the values must = 100. In this case, our table has 5 columns, and that’s why we have 5 sizes.
function resize(){
Flokzu.resizeTable( [[Table Name]] , [ 60, 10, 10, 10, 10 ] );
}
Flokzu.onInit(resize);
This script must be located in the tab Scripts, inside Visibility settings and Scripts.
In case you want to maintain the size in every task, you must locate it in -Master script-
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 3.5.0 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");
var 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.
Scripting with ChatGPT
Flokzu has an integration with ChatGPT, a Generative Artificial Intelligence model trained to understand naturally scripted conversations and answer questions about a wide variety of topics. In Flokzu, ChatGPT will be your assistant that will help you save time in some complex tasks.
Go to the Visibility settings and Scripts section on the right side of your screen. Then go to the Scripts tab
Select the User Task where you want to place the script and click the button.
In the popup window type a description of the behavior you want to obtain and press the ▶️ button to have the AI generate the script.
Flokzu will return a generated script with a brief explanation of each step.
To confirm the script press the Accept button. The script will be copied into the configuration window without the descriptive text.
You can modify or correct the script from the configuration window.
Despite AI assistance, we always recommend a human review of the generated code. Developers can make necessary adjustments to ensure proper functioning.
Artificial intelligence, while powerful, is not infallible so AI-generated code may not be perfect in all situations. Here are some reasons why JavaScript code may not work as expected:
Context Complexity: The AI relies on existing patterns and data to generate code. If the context or request is too complex or unique, the AI may not fully understand the target, which could lead to errors.
Training Data Dependency: AI is trained on a wide range of data, but cannot always anticipate all possible situations. If a case is unusual or not found in the training data, the generated code may not be optimal.
Input data errors: If the AI is provided with inaccurate input data, such as missing or misspelled field names, it may generate code that conflicts with the Flokzu library.
It is important to understand that, although this feature streamlines the development process, it does not replace the experience and knowledge of a developer. We recommend that technical users review and test the generated code to ensure that it meets their needs.
Updated on: 22/10/2023
Thank you!