Examples
Concrete, copy-pasteable examples covering the common patterns. Each is a complete, working feature — with the live reactive component rendered on its page and its source read straight off the file, so the demo and the code can never drift.
The examples#
Each page below renders its real reactive component inline — click it, it round-trips. They build from the smallest reactive component up to record-backed actions, live broadcasts, declared-once collections, and the flagship inbox that composes everything.
| Example | What it shows |
|---|---|
| Counter | State-backed — the smallest reactive component. Click → server → re-render, no DB row. |
| Payment split | Nested bracketed params, auto-collected siblings, and a live reactive_compute + reactive_text preview that paints before the debounced save. |
| Cross-tab chat | Record-backed action and broadcast → live cross-tab sync, zero JS. |
| Live todo list | Per-row record-backed components: add / toggle / rename / archive, optimistic toggle + delete, Enter-to-add, morph-in-place, broadcast on change. |
| Inline edit + dirty tracking | Show ↔ edit (Enter saves, Escape cancels) plus an “Unsaved” badge + leave-guard with zero shipped state. |
| Notifications / badges | Pure broadcast — a background event pushes a live re-render, plus a broadcast_js_to cross-tab pulse. |
| Reactive collections | Add / remove rows + a running count + an empty state, declared once with reactive_collection, optimistic dismiss + a self-dismissing flash. |
| File uploads & custom types | :file / [:file] params (multipart FormData), a nested-hash param alongside the file (#39), and a custom Phlex::Reactive.param_type. Code-first — no live demo. |
| Loading states | disable_with: + busy_on + the always-on aria-busy, with a latency toggle to make the pending window visible. |
| Client-only ops | on_client tabs / outside-close menu / accessible drawer — zero fetches, zero custom JS. |
| Failure surface | error_flash + data-reactive-error + dismiss_after: — what an adopter gets for free when an action fails. |
| Team inbox (flagship) | The whole toolkit in one UI: collection rows, optimistic archive that reverts on failure, cross-tab broadcast, an on_client kebab, and error flashes. |
Every headline feature now has a live page. Pick a capability:
| Feature | Where it's shown (live) |
|---|---|
Client-only ops — on_client + js (show/hide/toggle, set_attr/toggle_attr, focus, dispatch, transitions): zero round trips | Client-only ops, Todo list, Team inbox |
Client-side computes — reactive_compute + reactive_text (a live preview / char counter that paints with no round trip) | Payment split |
Declarative loading states — loading: / disable_with: / busy_on (+ the always-on aria-busy / data-reactive-busy) | Loading states, Todo list, Collections, Team inbox |
Dirty-field tracking — dirty: / track_dirty: / warn_unsaved: (enable Save only on change; warn before leaving) | Inline edit |
Optimistic visual hints — optimistic: (flip a checkbox / hide a row instantly; revert on failure) | Todo list, Collections, Team inbox |
Keyboard triggers — event: "keydown.enter" / "keydown.esc" (Enter-to-add, Escape-to-cancel) | Todo list, Inline edit |
Debounced / morph editing — debounce: live-as-you-type + reply.morph to keep the caret | Payment split, Inline edit |
Live broadcasts — broadcast_replace_to / broadcast_append_to / broadcast_js_to → cross-tab sync | Chat, Notifications, Todo list, Team inbox |
Failure surface — error_flash / data-reactive-error / dismiss_after: / timeout + offline | Failure surface, Team inbox |
Combobox keyboard navigation — listnav: (Arrow keys move a client highlight, Enter picks) | Searchable combobox demo |
File uploads & custom param types — :file / [:file] (multipart FormData), Phlex::Reactive.param_type | File uploads & custom types (code-first) |
File uploads (:file / [:file] params, multipart FormData) and custom param types (Phlex::Reactive.param_type) have a dedicated code-first walkthrough — no live demo, because a public upload endpoint is a storage/abuse surface. The payment split is the closest live cousin: the nested-params / auto-collected sibling-fields example that a FormData upload extends.