Get Started
Introduction
Components
Accordion
Badge
Button
Card
Checkbox
Command
Dialog
Dropdown Menu
Input
Select
Switch
Table
Tabs
Toast
Tooltip
Forms
Controlled Input
Field Arrays
Submit
Validation

Controlled Input

Demonstrates Signal ↔ input value synchronization patterns for two-way data binding.

See interactive examples below.

1import { createSignal } from '@barefootjs/dom'2import { Input } from '@/components/ui/input'34const [text, setText] = createSignal('')56<Input7  value={text()}8  onInput={(e) => setText(e.target.value)}9  placeholder="Type something..."10/>11<p>Current value: {text()}</p>

#Pattern Overview

The controlled input pattern uses value={signal()} combined with onInput to create two-way binding between a signal and an input element. This pattern enables real-time synchronization and derived computations.

1import { createSignal } from '@barefootjs/dom'2import { Input } from '@/components/ui/input'34const [text, setText] = createSignal('')56<Input7  value={text()}8  onInput={(e) => setText(e.target.value)}9  placeholder="Type something..."10/>11<p>Current value: {text()}</p>

#Examples

#Basic Two-Way Binding

Current value:

1import { createSignal } from '@barefootjs/dom'2import { Input } from '@/components/ui/input'34const [text, setText] = createSignal('')56<Input7  value={text()}8  onInput={(e) => setText(e.target.value)}9  placeholder="Type something..."10/>11<p>Current value: {text()}</p>

#Character Count

Characters: 0100 remaining
1import { createSignal, createMemo } from '@barefootjs/dom'23const [text, setText] = createSignal('')4const charCount = createMemo(() => text().length)5const remaining = createMemo(() => 100 - text().length)67<Input8  value={text()}9  onInput={(e) => setText(e.target.value)}10/>11<p>Characters: {charCount()}</p>12<p>{remaining()} remaining</p>

#Live Preview

Uppercase:

Word count: 0

1import { createSignal, createMemo } from '@barefootjs/dom'23const [text, setText] = createSignal('')4const uppercase = createMemo(() => text().toUpperCase())5const wordCount = createMemo(() => {6  const trimmed = text().trim()7  return trimmed === '' ? 0 : trimmed.split(/\\s+/).length8})910<Input11  value={text()}12  onInput={(e) => setText(e.target.value)}13/>14<p>Uppercase: {uppercase()}</p>15<p>Word count: {wordCount()}</p>

#Multi-Input Sync

Shared value:

1import { createSignal } from '@barefootjs/dom'23const [text, setText] = createSignal('')45// Both inputs share the same signal6<Input value={text()} onInput={(e) => setText(e.target.value)} />7<Input value={text()} onInput={(e) => setText(e.target.value)} />8<p>Shared value: {text()}</p>

#Key Points

Pattern Structure

  • value={signal()} - Binds signal value to input
  • onInput={(e) => setSignal(e.target.value)} - Updates signal on input
  • Use createMemo for derived values (character count, transformations)

Use Cases

  • Form validation with real-time feedback
  • Character/word counters
  • Live search/filter
  • Synced inputs (e.g., mirrored text fields)