Form Handling & Validation

Type-safe form processing with OorianForm and FormListener—no manual parsing required.

Two Form Classes

Form for traditional browser submission to external URLs. OorianForm for interactive, async forms that stay on the page and receive server updates.

Async Submission

OorianForm intercepts browser submission and sends data through the Oorian event system. The page stays loaded and can receive updates after submission.

Parameters API

Access submitted values through typed getters for String, int, long, double, float, and boolean. Multi-value support for checkboxes and multi-select fields.

Input Types

Built-in support for TextInput, PasswordInput, TextArea, Checkbox, RadioButton, Select, FileInput, HiddenInput, and more.

Validation Framework

ValidatedInput wraps any input with a fluent validation API. Thirteen built-in validators cover required, email, length, pattern, range, URL, phone, and more.

Cross-Field Validation

CompareValidator validates relationships between fields—password confirmation, date ranges, and numeric comparisons with six comparison operations.

Form vs. OorianForm

Oorian provides two form classes that serve different purposes. Form renders a standard HTML form that submits through traditional browser mechanisms—the browser navigates to the action URL. OorianForm intercepts submission and sends data through the Oorian event system, keeping the page loaded for server-side updates.

Form — Traditional Submission

Use Form when you need standard browser submission—posting to a payment gateway, submitting to an external API, or navigating to a response page. The browser sends a GET or POST request to the action URL and replaces the current page with the response.

Java
// Traditional form that posts to an external endpoint
Form form = new Form();
form.setAction("https://payment.example.com/checkout");
form.setMethod(FormMethod.POST);
form.setEncType(FormEncoding.URL_ENCODED);

HiddenInput orderId = new HiddenInput("orderId", "12345");
form.addElement(orderId);

Button payBtn = new Button("Proceed to Payment");
form.addElement(payBtn);

OorianForm — Interactive Submission

Use OorianForm for interactive forms within Oorian pages. The form submits asynchronously via AJAX, SSE, or WebSocket (depending on the page's communication mode). The page stays loaded, and you handle the submission in a FormListener.

Java
OorianForm form = new OorianForm();
form.registerListener(this, FormEvent.class);

TextInput name = new TextInput();
name.setName("name");
form.addElement(name);

Button submit = new Button("Send");
form.addElement(submit);

Most Oorian applications use OorianForm exclusively, since the framework is designed around pages that stay loaded and respond to events. Use Form when you need standard browser submission behavior—for example, posting to a payment gateway or submitting data to an external API that returns its own response page.

Interactive Forms with OorianForm

Implement the FormListener interface to handle OorianForm submissions. Give each input a name with setName(), register a listener, and access submitted values through the Parameters object in your onEvent method. After processing, update any element on the page to show results, errors, or confirmation messages.

Java
@Page("/contact")
public class ContactPage extends HtmlPage implements FormListener
{
    private TextInput nameInput;
    private TextInput emailInput;
    private TextArea messageInput;
    private Span statusLabel;

    @Override
    protected void createBody(Body body)
    {
        OorianForm form = new OorianForm();
        form.registerListener(this, FormEvent.class);

        nameInput = new TextInput();
        nameInput.setName("name");
        form.addElement(nameInput);

        emailInput = new TextInput();
        emailInput.setName("email");
        form.addElement(emailInput);

        messageInput = new TextArea();
        messageInput.setName("message");
        form.addElement(messageInput);

        form.addElement(new Button("Send Message"));

        statusLabel = new Span();
        form.addElement(statusLabel);

        body.addElement(form);
    }

    @Override
    public void onEvent(FormEvent event)
    {
        Parameters params = event.getParameters();

        String name = params.getParameterValue("name");
        String email = params.getParameterValue("email");
        String message = params.getParameterValue("message");

        // Process the form data
        sendContactEmail(name, email, message);

        statusLabel.setText("Thank you! Your message has been sent.");
        sendUpdate();
    }
}

The Parameters Class

The Parameters class provides typed access to form values. All values arrive as strings from the browser, and Parameters handles type conversion for you. Each getter returns null if the parameter is missing or cannot be parsed.

Java
Parameters params = event.getParameters();

// String value
String name = params.getParameterValue("name");

// Numeric values with automatic parsing
Integer age = params.getParameterValueAsInt("age");
Double salary = params.getParameterValueAsDouble("salary");

// Boolean (checkbox)
Boolean subscribe = params.getParameterValueAsBoolean("subscribe");

// Multi-value (checkboxes, multi-select)
List<String> selectedRoles = params.getParameterValues("roles");

// Check if parameter was submitted
if (params.containsParameter("agreeToTerms"))
{
    // User checked the terms checkbox
}

Available Typed Getters

getParameterValue(name)

Returns the first value as a String, or null if the parameter was not submitted.

getParameterValues(name)

Returns all values as a List<String>. Used for multi-select fields and checkbox groups.

getParameterValueAsInt(name)

Parses the value as an Integer, or returns null if missing or not a valid integer.

getParameterValueAsLong(name)

Parses the value as a Long, or returns null if missing or not a valid long.

getParameterValueAsDouble(name)

Parses the value as a Double, or returns null if missing or not a valid double.

getParameterValueAsFloat(name)

Parses the value as a Float, or returns null if missing or not a valid float.

getParameterValueAsBoolean(name)

Parses the value as a Boolean. Returns false if the parameter is missing.

containsParameter(name)

Returns true if the parameter exists in the submission, regardless of its value.

Validation Framework

OorianForm includes a validation framework that validates fields on submission. Each input field is wrapped in a ValidatedInput that defines validation rules through a fluent API. When validation fails, error messages are automatically displayed next to each invalid field.

Java
// Create a form with validation
OorianForm form = new OorianForm();
form.registerListener(this, FormEvent.class);

// Create input elements
TextInput emailInput = new TextInput();
emailInput.setName("email");
Span emailError = new Span();

PasswordInput passwordInput = new PasswordInput();
passwordInput.setName("password");
Span passwordError = new Span();

// Register validated inputs with rules
form.addValidatedInput(
    new ValidatedInput<>(emailInput, emailError)
        .required("Email is required")
        .email("Please enter a valid email address")
);

form.addValidatedInput(
    new ValidatedInput<>(passwordInput, passwordError)
        .required("Password is required")
        .minLength(8, "Password must be at least 8 characters")
);

// Add elements to the form
form.addElement(emailInput);
form.addElement(emailError);
form.addElement(passwordInput);
form.addElement(passwordError);
form.addElement(new Button("Sign In"));

Built-in Validators

Oorian includes thirteen built-in validators that cover common form validation scenarios. Validators are chained using the fluent API and evaluated in order—validation stops at the first failure for each field.

required(message)

Field must not be empty

email(message)

Must be a valid email address

minLength(n, message)

Minimum character length

maxLength(n, message)

Maximum character length

length(min, max, message)

Length must be within range

pattern(regex, message)

Must match a regex pattern

range(min, max, message)

Numeric value within range

url(message)

Must be a valid URL

phone(format, message)

Must match phone format

numeric(message)

Must be a numeric value

alphanumeric(message)

Letters and numbers only

creditCard(message)

Valid credit card number

date(format, message)

Must match a date format

Validator Chaining

Java
new ValidatedInput<>(usernameInput, usernameError)
    .required("Username is required")
    .minLength(3, "Username must be at least 3 characters")
    .maxLength(20, "Username must be 20 characters or fewer")
    .alphanumeric("Username must contain only letters and numbers");

Handling Validation in onEvent

In your FormListener, call form.validate(event) to validate all fields at once. The returned ValidationResult tells you whether the form is valid, and error messages are automatically displayed next to each invalid field.

Java
@Override
public void onEvent(FormEvent event)
{
    ValidationResult result = form.validate(event);

    if (result.isValid())
    {
        // All fields passed validation - process the form
        Parameters params = event.getParameters();
        String email = params.getParameterValue("email");
        String password = params.getParameterValue("password");
        createAccount(email, password);
    }

    // sendUpdate() pushes validation error messages to the browser
    sendUpdate();
}

Cross-Field Validation

For validation rules that compare two or more fields, use CompareValidator as a form-level validator. This is commonly used for password confirmation and date range validation. The CompareValidator.Operation enum supports EQUALS, NOT_EQUALS, LESS_THAN, LESS_THAN_OR_EQUALS, GREATER_THAN, and GREATER_THAN_OR_EQUALS.

Java
// Password confirmation
form.addFormValidator(
    new CompareValidator("password", "confirmPassword",
        CompareValidator.Operation.EQUALS)
        .withMessage("Passwords do not match")
);

// Date range validation
form.addFormValidator(
    new CompareValidator("startDate", "endDate",
        CompareValidator.Operation.LESS_THAN)
        .withMessage("Start date must be before end date")
);

Benefits

Asynchronous, Same-Page Processing

OorianForm submits asynchronously without a page reload. Process the data on the server and update any element on the page to show results, errors, or confirmation—all within the same page.

Type-Safe Parameters

The Parameters API provides typed accessors like getParameterValueAsInt() and getParameterValueAsBoolean(), eliminating manual parsing and type conversion.

Server-Side Validation

Validate submissions with Java code on the server with full access to your domain logic, database, and business rules. No need to duplicate validation in JavaScript.

Fluent Validation API

Chain validation rules with a readable fluent API—required(), email(), minLength(), pattern(), and ten more built-in validators. Rules are evaluated in order with automatic error display.

Cross-Field Validation

CompareValidator handles relationships between fields—password confirmation, date ranges, and numeric comparisons—without writing custom validation logic.

Clean Separation

The FormListener pattern cleanly separates form construction from submission handling, keeping your code organized and testable.