Two-Way Data Binding

Synchronize your state with form inputs using the "Value + Handler" pattern. PulsePoint favors explicit control over magic directives.

Text Inputs

Bind the value attribute to your state variable, and update the state using the oninput event.

search-bar.html
<div class="search-box">
  <input 
    type="text" 
    value="{query}" 
    placeholder="Search documentation..." 
    oninput="setQuery(event.target.value)" 
    class="border p-2 rounded"
  />
  
  <p>Searching for: <strong>{query}</strong></p>
  <small>Chars: {query.length}</small>
</div>

<script type="text/pp">
  const [query, setQuery] = pp.state("");
</script>

Checkboxes & Selects

Different inputs require different attributes. Use checked for checkboxes and value on the parent <select> element for dropdowns.

Remember: For checkboxes, always read event.target.checked instead of value.
preferences.html
<form>
  <!-- Checkbox Binding -->
  <label class="flex items-center gap-2">
    <input 
      type="checkbox" 
      checked="{enableNotifs}" 
      onchange="setNotifs(event.target.checked)" 
    />
    Enable Notifications
  </label>

  <!-- Select Dropdown Binding -->
  <div class="mt-4">
    <label>Region:</label>
    <select 
      value="{region}" 
      onchange="setRegion(event.target.value)"
      class="block border p-1 rounded"
    >
      <option value="us-east">US East</option>
      <option value="eu-west">EU West</option>
    </select>
  </div>
</form>

<script type="text/pp">
  const [enableNotifs, setNotifs] = pp.state(true);
  const [region, setRegion] = pp.state("us-east");
</script>

Managing Form Objects

For larger forms, store data in a single object. Use the spread syntax ...formData to update specific fields without losing the rest of the state.

registration-form.html
<form class="space-y-4">
  <div>
    <label class="block text-sm font-medium">Username</label>
    <input 
      type="text" 
      value="{form.username}"
      oninput="setForm({ ...form, username: event.target.value })"
      class="w-full border rounded p-2"
    />
  </div>

  <div>
    <label class="block text-sm font-medium">Email</label>
    <input 
      type="email" 
      value="{form.email}"
      oninput="setForm({ ...form, email: event.target.value })"
      class="w-full border rounded p-2"
    />
  </div>

  <p class="text-xs text-muted-foreground">
    Debug: {JSON.stringify(form)}
  </p>
</form>

<script type="text/pp">
  const [form, setForm] = pp.state({
    username: "",
    email: ""
  });
</script>
Event Handling Next: Conditional Rendering