> ## Knowledge Base Index
> Fetch the complete knowledge base index at: https://docs.flokzu.com/sitemap.xml
> Use this file to discover available pages before exploring further.
> Pure-Markdown content can be obtained by appending a '.md' suffix to the content URLs listed in the sitemap (without the trailing slash).

# Script development in Flokzu

### Introduction

It is often necessary to add a certain level of intelligence to forms, whether to perform complex calculations, validations, error detection, define conditional logic to hide/show fields, among many other possibilities.

To achieve this, Flokzu includes a *Script Engine* that provides several predefined functions at the form level to perform all kinds of validations, error detection, and algorithms. Scripts must be defined using **JavaScript** as the programming language, and most of the language’s features can be leveraged. The functions and shortcuts defined in this guide are intended to help speed up the development of algorithms and conditional logic functions.

| ✨ If you are not familiar with JavaScript development, you can use the [AI Assistant](/en/article/script-development-using-ai-assistant-39epc6/) to create scripts in your form. Simply describe the desired behavior and the assistant will generate the code for you.


# Development Methodology


In Flokzu, all logic must be defined **inside JavaScript functions**, which are invoked through *listeners* that associate them with specific form events (such as a field value change or the opening of a task). These *listeners* are described in detail later in this article.
The only exception to this rule is **autocalculated** fields, where the code can be written as a direct expression without the need to declare a function or register a *listener*, since Flokzu automatically infers which fields should be monitored.

The defined functions can use internal operations to manage field visibility, errors, and field read/write operations. In addition, you can use external libraries such as [Moment.js](https://momentjs.com/) and [Sweet Alert](https://sweetalert.js.org/docs/).

All variables used inside functions must be explicitly declared using the reserved keyword `var`. Flokzu **does not support global variables** (declared outside a function) nor the implicit declaration of variables (that is, assigning a value to an identifier without previously declaring it).



###### Field names used in scripts

|| 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]]).

Using special characters such as `{ } [ ] : < > = + ^ # $ / ! % * ? & |` at the beginning of field names can cause issues with custom scripts, especially because these names may be used as DOM identifiers, object keys in JavaScript, CSS/JS selectors, or in regular expressions. Many of these characters have reserved meanings in those contexts, which can lead to syntax errors or unexpected behavior.
To prevent issues, it is recommended to avoid using such characters in general, especially at the beginning of the field name.


### Listeners in calculated fields

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.

```javascript
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.

```javascript
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).

```javascript
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.

```javascript
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

```javascript
Flokzu.setHidden( [[field]] );
```

###### Make a field read only

```javascript
Flokzu.setReadOnly( [[field]] );
```

###### Make a field editable (not required)

```javascript
Flokzu.setEditable( [[field]] );
```

###### Make a field required

```javascript
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.

```javascript
Flokzu.setFieldValue( [[field]] , value );
```

###### Obtain a field value
This function is valid to all types of fields, with the **exception** of: ‘Title / Header’, ‘Table’ and ‘signature’ which are currently not supported.

```javascript
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.

```javascript
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.

```javascript
Flokzu.error( [[field]] , ‘message’ );
```

### Other useful functions

###### Get Instance Information
Returns instance information data: reference, process name, description, current task, creation date, assignment date, initiator, tags, and completion date.

```javascript
Flokzu.currentInstance()
```


###### Obtain the current user (email)
The email of the user that is currently logged in

```javascript
Flokzu.currentUser();
```

###### Get the current assignees
Returns the name and email of the users or the roles that are assigned to the task

```javascript
Flokzu.getCurrentAssignees();
```

###### Get current Date
Returns the current date, according to the time zone of the account, and the defined date format

```javascript
Flokzu.getCurrentDate();
```

###### Get current Time
Returns the current time, according to the time zone of the account, and in HH:mm:ss format

```javascript
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

```javascript
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. 

```javascript
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.

```javascript
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.

```javascript
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

### date-fns
Flokzu includes [date-fns](https://date-fns.org/docs/Getting-Started) for date/hour management, so **you do not need to import the library** in your custom scripts. The included version is the 4.1.0 and it can be used entirely in form scripts for anything related to date calculation.
All `date-fns` functions are available through the `dateFns` object, **you do not need to add an `import` statement to your scripts.** The `dateFns` object is already available globally in the application.

```javascript
var my_day = dateFns.parse('12-07-2027', 'MM-dd-yyyy', new Date()); // Creates a Date object
var full_date = dateFns.format(my_day, 'PPPP'); // 'Tuesday, December 7th, 2027 at 12:00:00 AM'
 
```

|| `date-fns` uses a **function-based API**, rather than methods on `Date` objects. Therefore, date operations must be performed using functions from `dateFns`.

**Correct:**

```javascript
dateFns.format(date, 'yyyy-MM-dd');
dateFns.addDays(date, 1);
dateFns.isBefore(date1, date2);
```

**Incorrect:**

```javascript
date.format('yyyy-MM-dd');
date.addDays(1);
date1.isBefore(date2);
```

| Note: `date-fns` uses its own date formatting syntax. For example, to format a date as `2026-08-27`, use `yyyy-MM-dd`, not `YYYY-MM-DD`. [Learn more](https://date-fns.org/v4.1.0/docs/format).



Flokzu also includes the `date-fns/locale` module by default, which is used to format dates using month names, weekday names, etc. in different languages (instead of the default English). It's used by passing a locale object as an option to functions such as `format`, `formatDistance`, `formatRelative`, etc.

```javascript
var date = dateFns.parse('14/07/2027', 'd/MM/yyyy', new Date());
console.log(  dateFns.format(date, 'PPPP', { locale: dateFns.locale.fr }) ); // "mercredi 14 juillet 2027"
```

```
🇪🇸 → dateFns.locale.es
🇫🇷 → dateFns.locale.fr
🇧🇷 → dateFns.locale.pt
🇩🇪 → dateFns.locale.de
🇬🇧 → dateFns.locale.en
```

###### Usage examples:

```javascript
// Format with month/weekday names in German
dateFns.format(new Date(2027, 9, 3), "PPPP", {locale: dateFns.locale.de});
// "Sonntag, 3. Oktober 2027"

// Relative distance ("3 days ago", etc.)
dateFns.formatDistance(new Date(2027, 8, 7), new Date(2026, 4, 14), {locale: dateFns.locale.pt});
// "mais de 1 ano"

// Relative format ("today at...", "yesterday at...")
dateFns.formatRelative(new Date(2027, 7, 25), new Date(2027, 7, 28), {locale: dateFns.locale.es});
// "el miércoles pasado a las 00:00"
```


|| Note on format tokens: with `format`, tokens like `EEEE` (full weekday name), `MMMM` (full month name), and `PPPP` (localized long date) are the ones that actually benefit from the locale — they change the language of the text. Numeric tokens like `HH:mm:ss` (the ones used in `calcDiff`) are not affected by the locale, since they're just numbers, not translatable text. 



###### 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.

```javascript
Example: swal( {type : 'error' , title : 'Error!' , text: 'Error message'} );
```

### mask / inputMask
With this library, you can apply input masks to your fields (phone numbers, documents, codes, etc.).
[Documentation](https://robinherbots.github.io/Inputmask/#/documentation)

||| This library only applies to Text fields. If the field passed as a parameter is of another type, the procedure is simply ignored.

Some examples you can implement:

```javascript
// Link a mask directly to a field
Flokzu.addMask([[Phone]], { mask: '9999-9999', placeholder: '*' }); // This is a custom mask
Flokzu.addMask([[Email]], { alias: 'email' }); // In this case, an alias applies, a mask defined by Inputmask.
Flokzu.addMask([[Field]], { alias: 'ip' });

// Remove a mask from a field
Flokzu.removeMask([[Field]]);


// Aliases and definitions that can be used in custom masks
Inputmask.extendDefinitions({ 'K': { validator: '[0-9Kk]', casing: 'upper' } });
Inputmask.extendAliases({ flokzuRut: { mask: '9{7,8}-K', greedy: false } });
Flokzu.addMask([[Rut]], { alias: 'flokzuRut' });
```

---

# 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?](https://docs.flokzu.com/en/article/how-to-set-up-visibility-by-script-kcs1n5/) 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.

```javascript
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.

```javascript
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’.

```javascript
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 date-fns 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*

```javascript
function calcDiff() {
  var start = dateFns.parse(Flokzu.getFieldValue([[Date 1]]), 'yyyy/MM/dd', new Date());
  var end = dateFns.parse(Flokzu.getFieldValue([[Date 2]]), 'yyyy/MM/dd', new Date());

  var weekdayCounter = 0;
  
  while (start <= end) {
    if (!dateFns.isWeekend(start)) {
      weekdayCounter++;
    }

    start = dateFns.addDays(start, 1);
  }

  return weekdayCounter;
}
```


*Script considering consecutive days*

```javascript
function calcDiff() {
  var start = dateFns.parse(Flokzu.getFieldValue([[Date 1]]), 'yyyy/MM/dd', new Date());
  var end = dateFns.parse(Flokzu.getFieldValue([[Date 2]]), 'yyyy/MM/dd', new Date());

  return dateFns.differenceInDays(end, start) + 1;
}
```


### Subtracting two Time fields with a Calculated field

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

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

**Step 3**
Add the script to the calculated field



```javascript
function calcDiff() {
  var t1 = Flokzu.getFieldValue([[Time 1]];
  var t2 = Flokzu.getFieldValue([[Time 2]];
  
  const baseDate = new Date(2000, 0, 1); // arbitrary reference date, same day for both

  var start = dateFns.parse(t1, 'HH:mm:ss', baseDate);
  var end = dateFns.parse(t2, 'HH:mm:ss', baseDate);

  var diffInSeconds = Math.abs(dateFns.differenceInSeconds(end, start));

  return dateFns.format( dateFns.addSeconds(baseDate, diffInSeconds), '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 date-fns documentation.


|| Note that no ‘listener’ was defined since as it is a calculated field, the listeners are inferred by Flokzu’s script engine automatically.

**Result**

![](https://storage.crisp.chat/users/helpdesk/website/5a899047-9b38-48ab-9475-31c8c63a3183/04e568a6-426f-4bec-b15f-a7aed8526175.png)

### 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

```javascript
function verifyDate(msg, button){
  
   if(button == 'Approve'){  // Name of the button we are interested in

       // Obtaining the date entered
       var dateEntered = dateFns.parse(Flokzu.getFieldValue([[Date 1]]), 'yyyy/MM/dd', new Date());

    
      // Obtaining the current date
       var currentDate = new Date();
       
      // If the date entered is after current date, we launch the error
       if (dateFns.isAfter(dateEntered, currentDate)){
           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:

```javascript
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.

```javascript
( Flokzu.getFieldValue([[A]])  *  Flokzu.getFieldValue([[B]]) ).toFixed(3)
```

|| Change ‘3’ for the number of decimals that you want.

