Using the editor

This is your code editor. Using Python, you can customize your form's code extensively to produce the functionality you want. Based on the components you chose in the UI builder, their layout and their individual property values and settings, the builder will automatically generate a base code structure that outlines your form. You can use this and build on it as you like by manipulating the existing code or using any of your custom variables.

Above the code editor, you have the option to add new File tabs to build your code with. As well as that, you have two buttons that you can use: Regenerate and Run.

Files

Files are a way for you to manage and sort your form’s code without maintaining it all in one compacted place. You can categorize different areas of your code into separate files, then simply import the desired data within to the file that requires it.

To create a new file:

  1. In the top panel of the code editor, click the + symbol.
  2. In the pop-up, type in a name for your file.
  3. Click Create.

📘

Default file

_init_ is the default file in which all automated code generations are created. This means that when you create or change a form, all of the relevant base code that is generated for the components used will be in _init_.

To import a specific variable, function, or class from one file to another, include this import sequence in the destination file:

from <file_name> import <variable_name>

In this case, <variable_name> must be replaced with the variable you need, and <file_name> must be replaced with the name of the file you want to import it from (excluding the .py suffix). This works the same way for functions and classes.

Run

To test your code after editing, you must click Run to update the form preview.

Regenerate

After your form's base code is generated, when you make changes to your form in the UI builder, the code editor will be modified accordingly. Clicking Regenerate will replace the code with an initial state based on the updated form UI. If there are any lines of custom code that you want to keep, make sure to have a copy of them with you before regenerating the code editor.

Component Path

Each component is accessed through its own unique path. In the case of a component that isn't placed in any group, the path is simply one element array containing the component’s ID:

['component_id']

If a component is placed within a group, the component's path is an array of the parent group's ID, the group's row index, and the component's ID:

['parent_group_id', <group_row_index>, 'component_id']

If a component is placed within a nested group (group_1 -> group_2 -> group_3), the component's path is an array of the parent group's IDs, the group's row indexes, and the component's ID:

['group_1', <group_1_row_index>, 'group_2', <group_2_row_index>, 'group_3', <group_3_row_index>, 'component_id']

-1 index points to the last row of the group:

['parent_group_id', -1, 'component_id']

Try in Playground

Event Handlers

Event handlers are special functions that allow users to add custom functionality on user-triggered and other events.
Event handler function name should have a strict format:

on_<component id>_<event type>

There are four types of events:

  • Component value change event - event type = change, in this case the function receives two arguments:
    • path - the path of the trigger component
    • value - updated value of the trigger component
  • Button click event - event = click, in this case the function receives one argument:
    • path - the path of the trigger button
  • on_<component ID>_message event - event = message, in this case the function receives two arguments:
    • path - the path of the trigger component
    • value - received message from the trigger component
  • on_<component ID>_wcevent - When the Web component sends an Event to the object. The function receives two arguments:
    • path - the path of the trigger component
    • value - received message from the trigger component
  • Group row deleted event - event type = deleted, this event is fired when a row in a group is being deleted by pressing X button. The handler function receives one argument:
    • path - the path of the trigger row
  • post_hook() - Fired when an item is being closed in the editor.
  • before_save_hook() - Fired before an item is saved in the editor in one of the following ways: Ctrl + S, Autosave, or when changing to a different item.
  • on_saved_hook() - Fired after before_save_hook() returns true and the item is saved.
  • before_status_change_hook() - Fired when the item's status is changed in one of the following ways: By shortcut, manually changing status in the editor, or by automatic update.
  • on_status_changed_hook() - Fired after before_status_change_hook() returns true and the status is changed.

Example:

### Value change event handler of the component with "prompt" ID
def on_prompt_change(path, value):
   ### your custom code
   return

### Button click event handler of the button with "submit" ID
def on_submit_click(path):
   ### your custom code
   return

### Message event handler of the component with "custom_web_component" ID
def on_custom_web_component_message(path):
   ### your custom code
   return

### Web component message event handler with "custom_web_component" ID
def on_custom_web_component_wcevent(path: List[Union[str, int]], value):
    ### your custom code
    return

### Group row deleted event handler of the component with "my_group" ID
def on_my_group_deleted(path):
   ### your custom code
   return

Custom functions

In the code editor, you can use a number of custom functions by importing them with the following:

import sa

You can access the functions from the sa. library. These functions are:

  • changeTab (path: list[(str, int)], index: int) - Changes the tab of a Tab component based on the provided parameters.
  • deleteRow (path: list[(str, int)]) - Deletes a row from the specified group using the given path. Here, the path should include the row index.
  • enable (path: list| (str, int)]) - Enables a component with the given path.
  • disable (path: list[(str, int)]) - Disables a component with the given path.
  • getGroupLength (path: list[(str, int)]) →> int - Returns the number of repeated rows within a Group component.
  • getPayload (name: str) →> any - To get a JSON file that's attached to the item.
  • getValue (path: list|(str, int)]) → any - Returns the value of the specified component.
  • postMessageToWebComponent (path: list[(str, int)], data: any) - Sends data to a Web component using python code.
  • repeatRow (path: list[(str, int)], index: int) →> list[(str, int)] - Appends a row to the group based on the provided path. This function returns the path of newly created row.
  • setLoading (state: bool, path: list[(str, int) ]) - Sets a Button component into a loading state.
  • setValue (path: list[(str, int)], value: (float, int, str, list[str], [(int, float), (int, float)], any)) - Sets the value of the specified component. The value type depends on the component.
  • Message types - Show a message on the bottom-left corner of the platform when executed.
    • showError (message: str) - Error message.
    • showInfo (message: str) - Info message.
    • showSuccess (message: str) - Success message.
    • showWarning (message: str) - Warning message.

HTTP Requests from The Code

To send HTTP requests, it is recommended to use the requests module, which was created by SuperAnnotate to replicate the Python requests module. The only difference is the browser limitation. In most cases, you won't see any difference.

Example:

import requests

def on_submit_click(path: List[Union[str, int]]):
    response = requests.request(
        url='https://your.domain.com/your/path',
        method ="GET",
        headers = None
    )

    ### Return response as a JSON object
    return response.json()

There is one important thing you need to remember while using this module - all the methods are asynchronous, meaning during the execution the UI will be blocked. Therefore, you should only use it with cases where the HTTP requests are fast enough. To use the asynchronous functionality, you can use asyncs sub module and add await to the function call to make it asynchronous.

Example:

import requests.asyncs as requests

async def on_submit_click(path: List[Union[str, int]]):
    response = await requests.request(
        url='https://your.domain.com/your/path',
        method ="GET",
        headers = None
    )

    ### Return response as a JSON object
    return response.json()