DEV Community

tengxgfyrz67s
tengxgfyrz67s

Posted on

form-handling

Form Handling in euv

Project Code:https://github.com/euv-dev/euv

Forms are the primary mechanism for user input in web applications. Whether you are building a login page, a search interface, a settings panel, or a data entry form, you need a robust way to capture, validate, and process user input. euv provides comprehensive form handling capabilities, including text inputs, checkboxes, dropdowns, text areas, file uploads, drag-and-drop uploads, and cascading dropdowns. This article covers all the form handling patterns available in euv.

Text Input

Text input is the most common form element. In euv, text inputs are created using the input element with r#type: "text". The value of the input is controlled by a reactive signal, and the on_input_value utility function handles user input events.

Here is a basic text input example:

let shared_text: Signal<String> = use_signal(|| "Type here...".to_string());

pub fn child_input(text_signal: Signal<String>, count_signal: Signal<i32>) -> VirtualNode {
    html! {
        div {
            input {
                r#type: "text"
                value: text_signal.get()
                oninput: on_input_value(text_signal)
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

In this example:

  • use_signal(|| "Type here...".to_string()) creates a reactive signal initialized with "Type here...".
  • text_signal.get() reads the current value for the input's value attribute.
  • on_input_value(text_signal) is an event handler that updates the signal whenever the user types.

This creates a controlled input component where the signal is the single source of truth for the input's value.

Checkbox

Checkboxes are used for boolean choices — on/off, yes/no, enabled/disabled. In euv, checkbox handling is similar to text input, but uses the on_change_checked utility function:

let is_checked: Signal<bool> = use_signal(|| false);

pub fn my_checkbox(checked_signal: Signal<bool>) -> VirtualNode {
    html! {
        div {
            input {
                r#type: "checkbox"
                checked: checked_signal.get()
                onchange: on_change_checked(checked_signal)
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

The on_change_checked function updates the signal with the checkbox's checked state whenever the user toggles it.

Dropdown / Select

Dropdown menus allow users to select from a list of options. In euv, dropdowns are created using the select element with option children. The on_change_value utility function handles selection changes:

let selected_value: Signal<String> = use_signal(|| "option1".to_string());

pub fn my_dropdown(selected_signal: Signal<String>) -> VirtualNode {
    html! {
        div {
            select {
                onchange: on_change_value(selected_signal)
                option { value: "option1", "Option 1" }
                option { value: "option2", "Option 2" }
                option { value: "option3", "Option 3" }
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

The on_change_value function updates the signal with the selected option's value whenever the user makes a selection.

Text Area

Text areas are used for multi-line text input, such as comments, descriptions, or messages. They work identically to text inputs but use the textarea element:

let message: Signal<String> = use_signal(|| "".to_string());

pub fn my_textarea(message_signal: Signal<String>) -> VirtualNode {
    html! {
        div {
            textarea {
                value: message_signal.get()
                oninput: on_input_value(message_signal)
                placeholder: "Enter your message..."
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

The on_input_value utility function works with text areas just as it does with text inputs.

File Upload

File uploads allow users to select files from their device. In euv, file uploads use the input element with r#type: "file". The browser's FileList and FileReader APIs are available for processing the selected files:

pub fn my_file_upload() -> VirtualNode {
    html! {
        div {
            input {
                r#type: "file"
                onchange: |event| {
                    // Access the selected files via the FileList API
                    // Use FileReader to read file contents
                }
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

When the user selects a file, the onchange event provides access to the FileList object, which contains the selected File objects. You can then use the FileReader API to read the file contents.

Drag-and-Drop Upload

For a more modern user experience, euv supports drag-and-drop file uploads. This involves handling ondrag and ondrop events:

pub fn my_drop_zone() -> VirtualNode {
    html! {
        div {
            ondrag: |event| {
                // Handle drag over event
            }
            ondrop: |event| {
                // Handle drop event
                // Access dropped files via DataTransfer
            }
            "Drag and drop files here"
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Drag-and-drop uploads provide a more intuitive interface for file selection, especially for multiple files.

Cascading Dropdowns

Cascading dropdowns are dropdowns whose options depend on the selection in another dropdown. This is common for location selection (country → state → city) or category selection (category → subcategory → item).

In euv, cascading dropdowns are implemented using reactive signals and the watch! macro:

watch!(celsius, |celsius_value: f64| {
    fahrenheit.set(celsius_value * 9.0 / 5.0 + 32.0);
});
Enter fullscreen mode Exit fullscreen mode

You can apply the same pattern to cascading dropdowns: when the first dropdown's value changes (observed by watch!), update the options available in the second dropdown.

Form Submission

Form submission is handled via the onsubmit event. In euv, you typically prevent the default form submission behavior and handle the submission programmatically:

pub fn my_form() -> VirtualNode {
    html! {
        form {
            onsubmit: |event| {
                // Prevent default form submission
                // Process form data
                // Send data to server
            }
            // Form fields...
            button { r#type: "submit", "Submit" }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Utility Functions for Form Handling

euv provides several utility functions that simplify form handling:

  • on_input_value(signal): Updates a signal from an input element's value on input events. Works with text inputs and text areas.
  • on_change_value(signal): Updates a signal from a select element's value on change events. Works with dropdown menus.
  • on_change_checked(signal): Updates a signal from a checkbox's checked state on change events.
  • use_toggle(): A convenience hook for boolean toggle state, commonly used for checkboxes and toggle switches.

These utilities eliminate boilerplate and make form handling code more concise.

Complete Form Example

Here is a complete example that combines multiple form elements:

#[derive(Clone, Default)]
struct MyCardProps {
    title: &'static str,
}

#[component]
pub fn my_card(node: VirtualNode<MyCardProps>) -> VirtualNode {
    let MyCardProps { title, .. } = node.try_get_props().unwrap_or_default();
    let children: VirtualNode = node.try_get_child_node();
    html! {
        div {
            h3 { title }
            children
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

This component can serve as a wrapper for form content, providing a consistent card-based layout.

For the form itself:

let shared_text: Signal<String> = use_signal(|| "Type here...".to_string());

pub fn child_input(text_signal: Signal<String>, count_signal: Signal<i32>) -> VirtualNode {
    html! {
        div {
            input {
                r#type: "text"
                value: text_signal.get()
                oninput: on_input_value(text_signal)
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Event Handling for Forms

euv supports a comprehensive set of event handlers for form elements:

  • oninput: Fires when the value of an input or text area changes (on every keystroke).
  • onchange: Fires when the value of a select element or checkbox changes.
  • onfocus: Fires when an element gains focus.
  • onblur: Fires when an element loses focus.
  • onkeydown / onkeyup: Fires when a key is pressed/released.
  • onsubmit: Fires when a form is submitted.

These events enable you to implement features like real-time validation, input masking, keyboard shortcuts, and focus management.

Summary

euv provides comprehensive form handling capabilities that cover all the common input patterns in web applications:

  • Text inputs with on_input_value for single-line text.
  • Checkboxes with on_change_checked for boolean choices.
  • Dropdowns with on_change_value for selection from options.
  • Text areas with on_input_value for multi-line text.
  • File uploads with FileList and FileReader APIs.
  • Drag-and-drop uploads with ondrag and ondrop events.
  • Cascading dropdowns with watch! for dependent selections.
  • Form submission with onsubmit for data processing.

By combining these form elements with euv's reactive signal system, you can build complex, interactive forms that provide real-time feedback and a smooth user experience.


Project Code:https://github.com/euv-dev/euv

Top comments (0)