Controlled Input
Problem
You can’t validate, format, or transform user input as they type because the DOM manages the input value directly. Features like real-time validation, input masking, or syncing multiple inputs become impossible or require awkward workarounds involving refs and manual DOM manipulation.
Solution
Drive form input values directly from state, making the component the single source of truth. This gives you complete control over input behavior and makes validation, formatting, and synchronization straightforward.
Example
This example demonstrates a controlled input that automatically converts user input to uppercase by synchronizing the DOM value with component state.
// Web Component that controls its input value through state
class ControlledInput extends HTMLElement {
constructor() {
super();
// Component state is the single source of truth
this.value = '';
}
connectedCallback() {
this.render();
const input = this.querySelector('input');
// On every input change, update state and sync back to DOM
input.addEventListener('input', (e) => {
// Transform input (convert to uppercase) before storing in state
this.value = e.target.value.toUpperCase();
// Force the DOM to reflect the transformed state value
input.value = this.value;
});
}
render() {
// Render input with current state value
this.innerHTML = `<input type="text" value="${this.value}">`;
}
}
customElements.define('controlled-input', ControlledInput);
Benefits
- Provides complete programmatic control over input values and behavior.
- Enables real-time validation and formatting as users type.
- Makes it easy to implement features like input masking or character limits.
- Simplifies syncing multiple inputs that depend on each other.
- Component state serves as single source of truth for form data.
Tradeoffs
- Requires more boilerplate code with state and change handlers.
- Every keystroke triggers a state update and re-render.
- Can cause performance issues with complex forms if not optimized.
- Makes it harder to integrate with non-React form libraries.
- Requires careful handling of cursor position for formatted inputs.