Interacting with Components

Overview

UI Components in Servoy are the elements that make up the user interface of a form. These components, often referred to as elements, are responsible for displaying data and allowing user interaction in a Servoy form. Common UI components include text fields, buttons, labels, combo boxes, tables, and more. Each UI component has properties and events that can be managed either through the Servoy design environment or dynamically in a form’s JavaScript file.

In Servoy, you can interact with UI components programmatically in the form’s JavaScript file using the elements object. This object allows you to access any UI component on the form by its name, so you can manipulate it by setting properties, binding events, or executing methods.

Accessing a UI Component

Each UI component can be accessed using elements.<component_name>. The component name is defined when you add the component to the form in the design environment.

Example:

// Access a text field named "customerName"
var customerNameField = elements.customerName;

Setting and Getting Properties

You can dynamically set or get properties of the UI components, such as their visibility, value, enabled state, or size.

  • Setting a Property: You can modify a UI component's properties such as value, visibility, enabled state, etc.

  • Getting a Property: You can retrieve the current state or value of a component.

Example:

// Set the value of a text field
elements.customerName.text = 'John Doe';

// Get the current value of a text field
var name = elements.customerName.text;

Common Methods

Developers frequently interact with components using simple methods to control their visibility, enablement, and other properties. Here are some key methods:

Show/Hide Components

Components can be displayed or hidden dynamically using the visible property. This is often used when certain components should only be shown based on specific conditions.

elements.myLabel.visible = false;  // Hide label
elements.myButton.visible = true;  // Show button

Enable/Disable Components

To control whether a component is usable, you can toggle the enabled property. Disabling a component can prevent user interaction when the application is in a specific state.

elements.myTextField.enabled = false;  // Disable text field
elements.mySubmitButton.enabled = true;  // Enable button

Common Events

Components in Servoy are event-driven, and various actions can be triggered based on user interaction. Here are some common events:

Click Event

The onAction event is the most commonly used event and is triggered when the user clicks a button or activates an interactive element like a checkbox. It's typically used to handle form submissions, button clicks, or other user actions.

Example Code for a Button Click:

/**
 * This method is called when the "Submit" button is clicked.
 * It handles form submission.
 * @param {JSEvent} event - The event object.
 */
function onSubmitButtonClick(event) {
    // Validate form fields before submission
    if (!elements.customerName.text) {
        plugins.dialogs.showWarningDialog('Validation Error', 'Customer Name is required.');
        return;
    }
    
    // Perform the form submission
    plugins.dialogs.showInfoDialog('Success', 'Form submitted successfully.');
}

In this example:

  • The onSubmitButtonClick() function is triggered when the Submit button is clicked.

  • The function performs validation before submitting the form, and if validation fails, it shows a warning dialog.

Focus Gained Event

The onFocusGained event is triggered when a user clicks into a field (like a text field) or navigates into it using the keyboard (e.g., pressing the "Tab" key). This event is commonly used to provide hints, pre-fill data, or make UI changes when the field becomes active.

Example Code for Focus Gained:

/**
 * This method is called when the customer name field gains focus.
 * It can be used to provide feedback or hints when the field is active.
 * @param {JSEvent} event - The event object.
 */
function onCustomerNameFocusGained(event) {
    // Highlight the text field when it gains focus
    elements.customerName.addStyleClass = 'light-yellow-background'; // Light yellow background
}

In this example:

  • The onCustomerNameFocusGained() method is called when the user clicks into the Customer Name text field.

  • It changes the background color of the field to light yellow, visually indicating that the field is currently active.

Focus Lost Event

The onFocusLost event is triggered when a UI component (such as a text field) loses focus, usually when the user clicks out of the field or navigates to another field. This event is useful for validating the input or resetting styles when the user finishes editing a field.

Example Code for Focus Lost:

/**
 * This method is called when the customer name field loses focus.
 * It can be used to validate input or reset the field's appearance.
 * @param {JSEvent} event - The event object.
 */
function onCustomerNameFocusLost(event) {
    // Reset the background color when focus is lost
    elements.customerName.addStyleClass = 'white-background; // Reset to white
    
    // Validate the customer name field
    if (!elements.customerName.text) {
        plugins.dialogs.showWarningDialog('Validation Error', 'Customer Name cannot be empty.');
        elements.customerName.requestFocus(); // Return focus to the field
    }
}

In this example:

  • The onCustomerNameFocusLost() method is called when the user leaves the Customer Name text field.

  • It resets the background color and validates that the field is not empty. If validation fails, the user is prompted, and the focus returns to the field.

Tab Sequence and Component Focus

Tab Sequence and Component Focus are related to the way users navigate through a form’s UI components (e.g., text fields, buttons, checkboxes) using the Tab key or mouse clicks. They are essential for ensuring a smooth and user-friendly interaction with the form.

Tab Sequence Tab sequence defines the order in which components receive focus when the user presses the Tab key. It allows users to navigate through form elements in a logical order (e.g., from one text field to the next). Servoy automatically assigns a tab sequence based on the order in which elements are placed on the form, but you can customize it to suit your form’s layout and workflow.

Component Focus Component focus refers to the current active UI component on a form. A component has focus when it is ready to receive user input or actions (e.g., a text field with focus can be typed into). You can programmatically set focus on a specific component to guide users through the form or after certain interactions (e.g., after validation).

Setting Tab Sequence

You can define the order in which components receive focus using their tabSeq property.

elements.fieldOne.tabSeq = 1;
elements.fieldTwo.tabSeq = 2;

Setting Focus on a Component

The requestFocus() method allows developers to set focus on a specific component programmatically, ensuring the user is directed to the right input field or component.

elements.myTextField.requestFocus();

Advanced

Custom Design-time Properties

Custom Design-Time Properties of UI components in Servoy are developer-defined properties that allow you to assign additional metadata or settings to specific UI elements (like buttons, text fields, labels, etc.) at design time. These properties are only available during the development phase and provide flexibility in controlling or modifying the behavior, appearance, or configuration of a UI component. They are useful for storing extra information that can later be accessed and acted upon in the form's JavaScript file during runtime.

Key Characteristics of Custom Design-Time Properties:

  • Customizable: You can define key-value pairs for any metadata or setting that applies to the UI component.

  • Design-Time Only: These properties exist only in the design phase and are not directly exposed to users during runtime, though they can be accessed and used in scripts.

  • Flexible: They allow you to define reusable or conditional behavior for UI elements without hard-coding it directly into the form's logic.

When to Use Custom Design-Time Properties of UI Components:

  • Conditional Behavior: You may want to set conditions or parameters for how a component behaves based on developer-set properties.

  • Modular UI Design: Design-time properties allow you to control behavior or layout dynamically, which can be helpful when creating modular or reusable components.

  • Configuration: These properties can be used to configure UI elements in various ways based on the specific context or scenario where the form will be used.

How to Define and Access Custom Design-Time Properties:

  1. Setting Custom Design-Time Properties:

    • Open the form in the Form Editor.

    • Select a UI component (such as a button or text field).

    • In the Properties panel, you’ll find the option to add custom properties under Design-Time Properties.

    • Add key-value pairs like "validation": "required" or "theme": "dark".

  2. Accessing Custom Design-Time Properties in JavaScript:

    • Once you have defined the custom design-time properties, you can access them in the form’s JavaScript file using the getDesignTimeProperty() function.

    var propertyValue = elements.componentName.getDesignTimeProperty('propertyName');

Examples of Custom Design-Time Properties for UI Components:

Required Field Validation

Imagine you want to mark certain fields in a form as required without hard-coding which ones are required. You can define a custom design-time property like "validation": "required" for specific fields. At runtime, you can access this property to validate the form.

Example: In the form designer, set the design-time property "validation": "required" for fields like customerName and email. Code to Access the Property:

/**
 * Validate the form by checking which fields are marked as "required" in their design-time properties.
 */
function validateForm() {
    var isValid = true;
    
    // Check if customerName is required
    if (elements.customerName.getDesignTimeProperty('validation') === 'required' && !elements.customerName.text) {
        plugins.dialogs.showWarningDialog('Validation Error', 'Customer Name is required.');
        isValid = false;
    }
    
    // Check if email is required
    if (elements.email.getDesignTimeProperty('validation') === 'required' && !elements.email.text) {
        plugins.dialogs.showWarningDialog('Validation Error', 'Email is required.');
        isValid = false;
    }

    return isValid;
}

In this case:

  • The form checks if a component (like customerName) has the validation property set to required.

  • If the field is required but empty, a validation error is shown.

Theming/Styling of Components

You might want to apply different styles (e.g., dark mode vs. light mode) to components like text fields or buttons based on a custom design-time property like "theme": "dark". This allows you to configure the appearance of components without hardcoding the style logic.

Example: In the form designer, set the custom design-time property "theme": "dark" for components that should use a dark theme. Code to Apply the Theme:

/**
 * Apply theming to components based on their design-time property "theme".
 */
function applyTheme() {
    // Check the theme of the customerName field
    var customerNameTheme = elements.customerName.getDesignTimeProperty('theme');
    
    // Apply dark theme
    if (customerNameTheme === 'dark') {
        elements.customerName.addStyleClass = 'dark-theme'; // Dark theme
    }

    // Check the theme of the submit button
    var submitButtonTheme = elements.submitButton.getDesignTimeProperty('theme');
    
    // Apply light theme
    if (submitButtonTheme === 'light') {
        elements.submitButton.addStyleClass = 'light-theme'; // Light theme
    }
}

In this case:

  • The custom property "theme": "dark" allows you to apply a dark background and white text dynamically, while "theme": "light" applies a different style.

Conditional Display Based on Properties

You may want to conditionally show or hide certain components based on a property, such as "display": "showOnAdmin", where specific fields are only shown if the user is an admin.

Example: In the form designer, set the design-time property "display": "showOnAdmin" for components that should only be visible to admins. Code to Handle Conditional Display:

/**
 * Conditionally show or hide components based on the "display" design-time property.
 */
function setComponentVisibility(userRole) {
    // Check the display property for the customer details section
    if (elements.customerDetails.getDesignTimeProperty('display') === 'showOnAdmin' && userRole !== 'admin') {
        elements.customerDetails.visible = false; // Hide the section for non-admin users
    } else {
        elements.customerDetails.visible = true; // Show the section for admin users
    }
}

In this case:

  • Components that should only be visible to admin users are controlled via the display design-time property.

  • Based on the user’s role, the components are shown or hidden accordingly.

Dynamic Field Formatting Based on Design-Time Properties

In some cases, you might want to format input fields differently based on the context. For example, you can set a custom design-time property "format": "currency" or "format": "percentage" and dynamically apply different formatting based on this property.

Example: Set the design-time property "format": "currency" for a field that accepts monetary values and "format": "percentage" for another field. Code to Handle Dynamic Formatting:

/**
 * Apply specific formatting to fields based on their design-time properties.
 */
function applyFieldFormatting() {
    // Check if the field should be formatted as currency
    if (elements.amountField.getDesignTimeProperty('format') === 'currency') {
        elements.amountField.text = utils.numberFormat(elements.amountField.text, "$###,###.00");
    }

    // Check if the field should be formatted as percentage
    if (elements.discountField.getDesignTimeProperty('format') === 'percentage') {
        elements.discountField.text = utils.numberFormat(elements.discountField.text, "###%");
    }
}

In this case:

  • The custom property "format" determines how the field values are formatted (currency or percentage).

Client Properties

Client properties for components in Servoy refer to additional attributes or settings that allow you to control and modify the behavior, appearance, or functionality of UI components specifically within the NG Client. These properties are typically used to customize how components look and behave, and they can be dynamically set and accessed within the form’s JavaScript file.

Client properties allow you to define special attributes that can be applied to components to:

  • Change how the component behaves under certain conditions.

  • Alter the appearance or style of a component (e.g., size, alignment, custom CSS classes).

  • Store metadata related to the component, which can be accessed and used later.

How and When to Use Client Properties: You use client properties when you need more fine-grained control over how a component behaves or appears in your application. These properties are especially useful when you want to:

  • Dynamically apply CSS classes or styles.

  • Modify component behavior based on user interaction or input.

  • Store additional information that can be referenced in other parts of your script.

Accessing and Changing Client Properties in a Form's JavaScript File To work with client properties in Servoy, you can use the putClientProperty() and getClientProperty() methods. These allow you to set and retrieve properties for a component dynamically in your form’s JavaScript file.

Syntax: Setting a Client Property:

elements.componentName.putClientProperty('propertyName', value);

Getting a Client Property:

var propertyValue = elements.componentName.getClientProperty('propertyName');

Example Use Cases for Client Properties:

Dynamically Adding and Removing CSS Classes

You might want to dynamically add or remove CSS classes from components to change their appearance based on user actions, validation, or events.

Example:

/**
 * Add a warning style to a field if it is invalid.
 */
function addWarningStyleToField() {
    var email = elements.customerEmail.text;

    // Basic email validation
    var emailPattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;

    if (!emailPattern.test(email)) {
        // Add a custom CSS class to highlight the field
        elements.customerEmail.putClientProperty('cssClass', 'invalid-input');
    } else {
        // Remove the custom CSS class if the input is valid
        elements.customerEmail.putClientProperty('cssClass', '');
    }
}

In this example:

  • putClientProperty('cssClass', 'invalid-input') adds a custom CSS class invalid-input to the email field if the email is invalid. This class can be defined in your CSS to style the field (e.g., a red border or background).

  • When the input becomes valid, the CSS class is removed by setting it to an empty string.

Storing Metadata in Client Properties

You might want to store additional metadata in a component for future reference. For example, you could store whether a field is required or optional using client properties, making it easier to validate the form dynamically.

Example:

/**
 * Check if the field is required based on client properties and perform validation.
 */
function validateFormFields() {
    // Check if the customerName field is required
    if (elements.customerName.getClientProperty('required') && !elements.customerName.text) {
        plugins.dialogs.showWarningDialog('Validation Error', 'Customer Name is required.');
        return false;
    }

    // Check if the email field is required
    if (elements.customerEmail.getClientProperty('required') && !elements.customerEmail.text) {
        plugins.dialogs.showWarningDialog('Validation Error', 'Email is required.');
        return false;
    }

    return true; // Return true if all validations pass
}

In this example:

  • getClientProperty('required') checks whether a field is required based on its client property.

  • You can store the "required": true property on any form field in your design-time settings and access it later to enforce validation.

Changing Component Behavior Dynamically

You may need to adjust the behavior of a component (e.g., making a button inactive) based on certain conditions at runtime. For example, a button can be enabled or disabled dynamically by using client properties.

Example:

/**
 * Enable or disable the submit button based on form validation.
 */
function updateSubmitButtonState() {
    var isFormValid = validateFormFields();

    if (isFormValid) {
        // Enable the submit button
        elements.submitButton.putClientProperty('enabled', true);
    } else {
        // Disable the submit button
        elements.submitButton.putClientProperty('enabled', false);
    }
}

In this example:

  • putClientProperty('enabled', true) or putClientProperty('enabled', false) is used to dynamically enable or disable the submit button based on the form’s validation state.

  • This approach allows you to control the button’s interactivity based on user actions.

Setting Custom Placeholder Text for Input Fields

You can use client properties to set custom placeholder text for input fields dynamically. This is useful when you want to provide user guidance on what type of data they should enter into the field.

Example:

/**
 * Set placeholder text dynamically for input fields.
 */
function setPlaceholderText() {
    elements.customerName.putClientProperty('placeholderText', 'Enter your full name');
    elements.customerEmail.putClientProperty('placeholderText', 'Enter a valid email address');
}

In this example:

  • putClientProperty('placeholderText', 'Enter your full name') sets placeholder text for the customerName field, giving the user a hint about what to enter.

  • Placeholders can be useful for providing contextual help inside form fields.

Controlling Custom Tooltips

You can dynamically set tooltips for components using client properties. Tooltips are small pop-up hints that appear when a user hovers over a component.

Example:

/**
 * Set tooltips for form components based on their context.
 */
function setCustomTooltips() {
    elements.customerName.putClientProperty('toolTipText', 'Enter your full legal name.');
    elements.customerEmail.putClientProperty('toolTipText', 'Your email will be used for account notifications.');
}

In this example:

  • putClientProperty('toolTipText', '...') is used to set a custom tooltip for the customerName and customerEmail fields, helping users understand what information is expected.

Last updated