﻿# System functions in widgets

> [HTML Version](widget_functions.html)

Client scripts in widgets support functions that are called automatically when working with a widget. Here is a list of system functions:

- The initialization function. This function is called as the widget is initialized, before the interface template is displayed.

- The function checking the widget’s display settings. This function is called after the initialization function. It returns \[OBJECT\] if the widget should be displayed and \[OBJECT\] if it shouldn’t.

- The rendering completion function. This function is called after the widget template is fully rendered in the browser. If the [Load the contents asynchronously](common_widget_settings.md#load-asynchronously) option is enabled in the widget settings, the function is called upon the completion of rendering the widget itself, but before its content is rendered.

- The destroy function. This function is called in order to end the widget’s work and free system resources from the data associated with its operation.

- The validation function. This function is called when the user tries to save the form. It checks whether the form’s fields are filled out correctly.

These functions are optional. You can use them in the scripts and select them on the [Settings](designer-tabs.md#settings) tab in the interface designer.

By default, the following functions are called if they are defined in the script:

- \[OBJECT\] is called upon the widget’s initialization.

- \[OBJECT\] is called when conditions for displaying the widget are checked.

- \[OBJECT\] is called when the widget’s rendering is completed.

- \[OBJECT\] is called when the widget’s work ends.

There is no default validation function.

## onInit()

By the time the execution of the function starts, the input data is loaded to the widget’s context, \[OBJECT\]. You can add whatever data is missing to the function’s body, and it will be used to manage the way the widget is displayed or to execute custom functions. Also, in the function’s body you can call [API methods](extention-api.md) or server functions.

````
async function onInit (): Promise<void> \{  
   // Function's body  
\}

### ````
Use case

Let’s say you need to create a widget that will show a table displaying full names of users alongside with their birth dates.

Add the \[OBJECT\] variable of the [Table](360010201779.md) type to the widget, as well as two [String](https://brix365.com/en/help/360009707032.html#string) type variables that the table will include: \[OBJECT\] and \[OBJECT\].

Place the \[OBJECT\] variable on the modeling canvas. In the client script, write the \[OBJECT\]** **function:

````
async function onInit (): Promise<void> \{  
    const users = await System.users.search().size(100).sort('\_\_name', true).all();  
    for (const user of users) \{  
        let item = Context.data.users\!.insert();  
        item.name = user.data.\_\_name;  
        item.birthDate = user.data.birthDate ? user.data.birthDate.format('L') : '';  
    \}  
    Context.data.users = Context.data.users;  
\}

## ````
canRender()

Use this function when you need to display a widget template only when a certain condition is met, for example, when certain input data is filled out in the context. 

````
async function canRender (): Promise<boolean> \{  
   // Function's body (must return true/false)  
\}

````
The \[OBJECT\] function is different from the [Hide](common_widget_settings.md) system field. If the value of the **Hide** field evaluates to \[OBJECT\], the widget template is still rendered, but it’s not visible to users because it is marked as hidden in the web element’s styles. When the \[OBJECT\] function returns \[OBJECT\], the template isn’t rendered at all. This can be important, for instance, when you create complex widgets with required fields. In this case an error can occur if certain fields on a hidden template are left empty.

### Use case

Let’s say you need to create a widget to display a brief overview of each item of the **Contracts** app.

Create two variables: one with the code \[OBJECT\], of the [Date](360009707032.md#date-time) type, and one with the code \[OBJECT\], of the [Number](360009707032.md#number) type. As an input parameter, specify the variable storing a [Document type app](360009923631.md). In our case, it will be used to store an item of the **Contracts** app.  

This widget will be reused in different business processes and on forms of different apps that have a [Document type app](360009923631.md) in the context. Another condition is that the widget’s template should not be displayed if the input field is empty.

To make this possible, add an input variable with the code \[OBJECT\] storing a [Document app](360009923631.md). Also, create additional \[OBJECT\] and \[OBJECT\] variables. Their types must match the corresponding fields in the **Contracts** app. Uncheck the **Input** and **Output** boxes for these variables.

Place the \[OBJECT\] and \[OBJECT\] variables on the form and mark them as **Read only**. To make the widget stand out on the page, add a border to it. To do that, go to the **HTML styles** field and enter the following: 

````
border: 1px solid gray;

````
In the client script, write the \[OBJECT\] and \[OBJECT\]** **functions:

````
async function onInit (): Promise<void> \{  
   if (\!await canRender()) \{  
      return;  
   \}  
   const appItem = await Context.data.app\!.fetch();  
   Context.data.date = appItem.date;  
   Context.data.number = appItem.number;  
\}  
async function canRender (): Promise<boolean> \{  
   return \!\!Context.data.app; // Returns true if the app field is filled in  
\}

````
After you publish the script, you can place the widget on the form of any other app that has a variable for a [Document type app](360009923631.md) and map this variable with the input field of the widget.

Now, the widget will be displayed on pages of items that have this field filled out. If the field is empty, nothing will be shown, neither the border nor the hidden web elements of the widget.

## onLoad()

This function is used to load styles and appearance settings for the widget. Using it, you can change the color, hide or show a widget that is not available for editing in the interface designer.

````
async function onLoad(): Promise<void> \{  
   // Function's body  
\}

### ````
Use case

Let’s assume that there is the **Assign** button on the start event form. When the user clicks this button, they assign a task performer, and the process moves on to the next step. To draw the user’s attention to the button, let’s change its color.

By default, the start event buttons style cannot be customized. Therefore, the color will be set using the \[OBJECT\] function.

To do this, when editing the event form in the interface designer, on the **Scripts** tab, write the following:

````
async function onLoad (): Promise<void> \{  
    const processButton: any = Array.from(document.querySelectorAll('button.btn.btn-primary')).find((btn: any) => btn.innerText.includes('Assign'));  
        processButton.style.backgroundColor = '#28a745';  
        processButton.style.color = '#ffffff';  
\}

````
After the function is performed, the button on the form will be green with white text.

## Destroy() function

You can end the widget’s work using the \[OBJECT\] function The widget will stop performing its functionality, and the data created during its operation will be cleared.

````
async function destroy(): Promise<void> \{  
   // Function body  
\}

### ````
Use case

For example, a page contains a report that displays data from different apps. A script for automatic refreshing for a certain period of time is configured for the report. When the user closes the page, the countdown to refresh continues and the data from apps is requested. If the user re-visits the page, a new time count starts, which causes an error on the server.

To avoid errors and prevent the system from overloading, you can apply the destroy function to the widget. Then when the page is closed, the time counting will stop and the data will not be updated.

Let’s write the \[OBJECT\] function in the the widget client scripts:

````
async function onInit(): Promise<void> \{  
    // await refresh();  
    setIntervalRefresh();  
\}  
  
let intervalID: number;  
  
declare const window: \{  
    setInterval: (fn: () => void, interval: number) => number;  
    clearInterval: (clearInterval: number) => void;  
\};  
  
async function setIntervalRefresh () \{  
    intervalID = window.setInterval(() => \{  
        refresh();  
    \}, 3000);  
\}  
  
async function destroy(): Promise<void> \{  
    window.clearInterval(intervalID);  
\}

## ````
Custom validation function

You can create a function that will check whether a form is filled out correctly. In this function, you can add the necessary checks that you want to apply along with the existing standard ones when a user attempts to save the form. For example, you can set validation for field values.

To apply the function, select it in the **Validation** field on the [Settings](designer-tabs.md#settings) tab in the interface designer.

Information about validation errors will be displayed under the fields with invalid information. Moreover, a list or all errors will be displayed at the top of the form. If at least one error is found during standard or custom validation, it is impossible to save the form.

If several custom widgets with a validation function are placed on one form, the [validation result](https://tssdk.brix365.com/en/interfaces/_02_types_.validationresult.html) will be checked for each function.

**(user-validation-3.png)**

When describing the validation function, you can create additional checks for fields, customize error display, and manage the validation of hidden form fields. See more in the [Set up custom validation](user-validation.md) article.