# Validator

# Validator

# Description

The Validator is a utility component designed to orchestrate and centralize the validation of multiple UI elements. It registers components that implement validation, tracks which of them the user has interacted with, and triggers visual state updates based on their current validity. Use this component when you need to validate forms or groups of input components in a fluent and efficient manner.

# Usage

Instantiate the Validator using the static helper from Tesserae.UI. Register your UI components (such as TextBox or Dropdown) with custom validation logic. This allows you to show validation messages dynamically as users interact with the form or when the entire form is revalidated (for instance, on form submission).

Below is a simple example demonstrating its usage:

using System;
using Tesserae;
using static Tesserae.UI;

public class MyForm
{
    public void Initialize()
    {
        // Create the validator
        var validator = Validator().OnValidation(validity =>
        {
            Console.WriteLine(validity == ValidationState.Invalid
                ? "Some fields are invalid"
                : "All fields are valid");
        });

        // Create input controls
        var nameTextBox = TextBox("").Required();
        var ageTextBox = TextBox("").Required();

        // Register validation for the name TextBox: must not be empty.
        nameTextBox.Validation(tb =>
            string.IsNullOrWhiteSpace(tb.Text) ? "Please enter your name" : null, 
            validator);

        // Register validation for the age TextBox: must be a valid positive integer.
        ageTextBox.Validation(tb =>
            Validation.NonZeroPositiveInteger(tb) ?? null, 
            validator);

        // Optionally, check if all values are valid
        Console.WriteLine("Is form valid? " + validator.AreCurrentValuesAllValid());
    }
}

# Methods

  • Register<T>(ICanValidate<T> component, Func<bool> wouldBeValid, Action validate) where T : ICanValidate<T>
    Registers a UI component with its validation logic.
    • component: The UI component implementing ICanValidate<T>.
    • wouldBeValid: A function returning true if the component's current value is valid.
    • validate: An action that forces the component to revalidate its current value.

  • RegisterFromCallback(Func<bool> isInvalid, Action onRevalidation)
    Registers custom validation logic without being tied to a specific component.
    • isInvalid: A function determining if the custom validation condition is invalid.
    • onRevalidation: An action to execute during a revalidation cycle.

  • OnValidation(OnValidationHandler onValidation)
    Adds a callback that is invoked after a validation cycle occurs.
    • onValidation: A delegate that receives the current ValidationState.
    Returns the Validator instance to support fluent chaining.

  • Debounce(int delayInMs)
    Configures the debounce delay for the validation callbacks.
    • delayInMs: The delay in milliseconds (must be at least 1).
    Returns the Validator instance.

  • Debounce(int delayInMs, int maxDelayInMs)
    Configures both the debounce delay and a maximum delay for the validation callbacks.
    • delayInMs: The delay in milliseconds.
    • maxDelayInMs: The maximum allowable delay in milliseconds.
    Returns the Validator instance.

  • AreCurrentValuesAllValid()
    Checks whether the current values across components would be valid without triggering visual state updates for untouched fields.
    Returns a Boolean indicating whether values are valid.

  • Revalidate()
    Triggers a full revalidation of all registered components, updating their visual validation states, and fires any attached validation events.
    Returns a Boolean indicating whether all components are valid.

# Properties

  • IsValid
    A Boolean property that triggers a full revalidation when accessed. It returns true if every registered component is validated successfully, otherwise false.

# Samples

# Basic Form Validation Example

The following sample demonstrates how to set up a simple form with two text boxes. Each text box has its own validation logic, and a validator is used to update the UI based on the current validity of the form.

using System;
using Tesserae;
using static Tesserae.UI;

public class FormExample
{
    public IComponent BuildForm()
    {
        // Create the validator and set up a handler for validation events.
        var validator = Validator().OnValidation(validity =>
        {
            // Log the current state – useful for enabling/disabling submit buttons.
            Console.WriteLine(validity == ValidationState.Invalid ? "Invalid!" : "Valid!");
        });

        // Create two text boxes with validation rules.
        var nameBox = TextBox("").Required();
        nameBox.Validation(tb =>
            string.IsNullOrWhiteSpace(tb.Text) ? "Name cannot be empty" : null,
            validator);

        var ageBox = TextBox("").Required();
        ageBox.Validation(tb =>
            Validation.NonZeroPositiveInteger(tb) ?? "Age must be a positive integer",
            validator);

        // Use a button to force validation on click.
        var validateButton = Button("Validate").OnClick((s, b) => validator.Revalidate());

        // Arrange components in a vertical stack.
        return Stack().Children(
            Label("Name").SetContent(nameBox),
            Label("Age").SetContent(ageBox),
            validateButton
        );
    }
}

# See also

  • TextBox: Often used in forms alongside Validator.
  • Dropdown: Another input component that can be validated.
  • Form Handling Patterns: For guidance on handling multiple input validations.