Module: Phlex::Reactive::ClientBindings

Extended by:
ActiveSupport::Concern
Includes:
Phlex::Reactive::Component::DSL, Phlex::Reactive::Component::Helpers
Included in:
Component
Defined in:
lib/phlex/reactive/client_bindings.rb

Overview

The blessed CLIENT-ONLY include (issue #180). A view that only shows/hides (reactive_show), filters (reactive_filter), computes client-side (reactive_compute), or runs zero-round-trip ops (on_client/js) — with NO server actions and NO signed token — includes this instead of the full Phlex::Reactive::Component.

Why it exists: including the full Component pulls in Streamable, whose class/instance methods (replace/update/append/prepend/remove, to_stream_*) collide by NAME with an app's own Turbo-stream concern — so adopters cherry-picked an internal module and hand-rolled a token-less root (and defined a dummy #id "never read at render" just to keep phlex_reactive:doctor quiet). ClientBindings is that missing seam, blessed:

class ExerciseFilter < ApplicationComponent
include Phlex::Reactive::ClientBindings

reactive_scope :form
def reactive_values = { role: @role }

def view_template
  div(**reactive_root) do              # token-less: no #id required
    select(name: "form[role]") { role_options }
    div(**reactive_show(if: { role: "individual" })) { demographics }
  end
end
end

It includes the DECLARATION DSL and the view Helpers, but NOT Streamable (nothing to clobber) or Identity (no token). So a ClientBindings class never enters Streamable.registered_classes and is invisible to phlex_reactive:doctor's #id check — no dummy #id, no nag.

The client-only DSL macros (reactive_scope, reactive_compute) work; the SERVER-ACTION macros (action, reactive_record, reactive_state) RAISE at class-definition time — without Identity they could only silently no-op (sign nothing, dispatch nowhere), so the guard fails loudly (the guard lives in Component::DSL#require_server_actions!, keyed on Identity presence).

Helpers is token-tolerant (issue #180): reactive_attrs emits a token only when reactive_token is available, and reactive_root uses #id only when defined — so the client-only view helpers work with no Identity/Streamable.

The full Component includes ClientBindings too (ONE implementation of the client-only surface), then layers Streamable + Identity on top — so a token-bearing reactive_root is a SUPERSET, not a fork.

Constant Summary

Constants included from Phlex::Reactive::Component::Helpers

Phlex::Reactive::Component::Helpers::EMPTY_PARAMS_JSON, Phlex::Reactive::Component::Helpers::LEGACY_SHOW_CONNECTIVE_KEYS, Phlex::Reactive::Component::Helpers::LEGACY_SHOW_PREDICATE_KEYS, Phlex::Reactive::Component::Helpers::LISTNAV_ACTIONS, Phlex::Reactive::Component::Helpers::OPTIMISTIC_CLASS_OPS, Phlex::Reactive::Component::Helpers::SHOW_CONDITION_KEYS

Constants included from Phlex::Reactive::Component::DSL

Phlex::Reactive::Component::DSL::MIRROR_ID_SELECTOR

Method Summary

Methods included from Phlex::Reactive::Component::Helpers

#busy_on, #compute_inputs_param, #compute_mirror_param, #js, #mark_authorized!, #nested_attributes, #nested_update!, #on, #on_client, #reactive_attrs, #reactive_compute_attrs, #reactive_connection_id, #reactive_field, #reactive_filter, #reactive_input, #reactive_listnav, #reactive_root, #reactive_select, #reactive_show, #reactive_show_targets, #reactive_text, #reply