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)
}
}
}
}
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'svalueattribute. -
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)
}
}
}
}
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" }
}
}
}
}
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..."
}
}
}
}
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
}
}
}
}
}
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"
}
}
}
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);
});
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" }
}
}
}
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 oninputevents. Works with text inputs and text areas. -
on_change_value(signal): Updates a signal from a select element's value onchangeevents. Works with dropdown menus. -
on_change_checked(signal): Updates a signal from a checkbox's checked state onchangeevents. -
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
}
}
}
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)
}
}
}
}
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_valuefor single-line text. -
Checkboxes with
on_change_checkedfor boolean choices. -
Dropdowns with
on_change_valuefor selection from options. -
Text areas with
on_input_valuefor multi-line text. -
File uploads with
FileListandFileReaderAPIs. -
Drag-and-drop uploads with
ondragandondropevents. -
Cascading dropdowns with
watch!for dependent selections. -
Form submission with
onsubmitfor 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)