Module: Phlex::Reactive::Component::Helpers

Extended by:
ActiveSupport::Concern
Included in:
Phlex::Reactive::ClientBindings
Defined in:
lib/phlex/reactive/component/helpers.rb

Overview

The view-side helper surface of Component (issue #115): the reply/js builders, the root-element attribute helpers (reactive_attrs/ reactive_root), the trigger builders (on/on_client) with their hint vocabularies, the form-binding helpers (reactive_field/input/select/ text/busy_on/reactive_compute_attrs), and the nested-attributes helpers. Everything a view_template spreads or calls — no registries, no signing (those live in DSL and Identity).

Constant Summary collapse

EMPTY_PARAMS_JSON =

Attributes for an element that triggers an action. button(**on(:toggle)) { "○" } form(**on(:save, event: "submit")) { ... } input(**on(:update, event: "input", debounce: 300)) # live-as-you-type

Extra keyword args become explicit params merged over collected form fields. For click triggers we force type="button" so a bare button inside a

can't submit it and cause a full-page navigation.

debounce: (milliseconds) coalesces rapid events (e.g. keystrokes on an "input" trigger) into ONE round trip fired after the quiet period — so live-update-as-you-type doesn't POST per keystroke. A blur flushes a pending dispatch so the last edit is never dropped. Omit it for the immediate-dispatch default.

confirm: (a message string) gates the action behind a confirmation prompt (issue #52). Destructive reactive triggers can't use Hotwire's data-turbo-confirm — the reactive controller calls preventDefault and enqueues the POST itself, so Turbo's confirm handling never runs. The client shows window.confirm(message) FIRST and bails before any enqueue/debounce if the user declines (and prevents the native default so a submit trigger can't navigate on cancel). Omit it for no prompt. button(**on(:destroy, confirm: "Really delete this item?")) { "Delete" }

event: is interpolated verbatim into the Stimulus action descriptor (#{event}->reactive#dispatch), so any Stimulus event string works — including its native KEYBOARD FILTERS. Pass event: "keydown.enter" for Enter-to-submit or event: "keydown.esc" for Escape-to-cancel, and the action fires only on that key — no separate option, no client code, and key stays free as an ordinary action-param name (on(:switch, key: …)):

input(**on(:add, event: "keydown.enter"))      # Enter submits
button(**on(:cancel, event: "keydown.esc"))     # Escape cancels

Combobox keyboard navigation is the standalone reactive_listnav (issue #181 removed the on(…, listnav:) kwarg — it duplicated reactive_listnav while skipping its blank-selector validation). Compose it via mix:

input(**mix(on(:search, event: "input", debounce: 300), reactive_listnav))

The verbatim JSON for an empty explicit-params payload. The common trigger (on(:increment), no params) hits this on EVERY render — skipping params.to_json (which re-serializes {} to the same "{}" each time) avoids a per-render allocation while keeping the wire format byte-identical.

"{}"
LISTNAV_ACTIONS =

The keyboard filters appended to a listnav trigger's data-action. Each is a client-only handler (no POST) except Enter, which clicks the highlighted option's own reactive trigger. Stimulus binds these natively.

[
  "keydown.down->reactive#listnavNext",
  "keydown.up->reactive#listnavPrev",
  "keydown.enter->reactive#listnavPick",
  "keydown.esc->reactive#listnavClose"
].freeze
NESTED_NEW_ROW =

The index placeholder a template row carries in its field names; the client swaps it for a fresh unique index on every add. Referenced by both sides of the wire — change it nowhere.

"NEW_ROW"
SHOW_CONDITION_KEYS =

The conditions-language kwargs (issue #180): if:/if_any:/unless: — compiled by Phlex::Reactive::ShowConditions into the DNF wire. The ONE vocabulary; there are no predicate kwargs any more.

%i[if if_any unless].freeze
LEGACY_SHOW_PREDICATE_KEYS =

The removed 0.9.5 surface (issue #180 clean break): each of these kwargs — and a positional field — now raises a GUIDED error printing the if:/if_any:/unless: rewrite. Kept only to detect the legacy call shape; nothing here reaches the wire.

%i[equals not in gte gt lte lt].freeze
LEGACY_SHOW_CONNECTIVE_KEYS =
%i[all any].freeze

Instance Method Summary collapse