Class: Forms::TagField
- Inherits:
-
Phlex::HTML
- Object
- Phlex::HTML
- Forms::TagField
- Includes:
- Phlex::Reactive::ClientBindings
- Defined in:
- lib/forms/tag_field.rb
Overview
A model-bound tag/chip input, composed from phlex-reactive's CLIENT-ONLY tag primitives (form state, no token, zero round trips). phlex-forms owns the polished chrome — daisyUI styling, model binding, the hidden comma-joined field — while phlex-reactive owns the behavior contract.
f.field :tags, as: :tags, suggestions: %w[Ruby Rails Hotwire Postgres]
f.field :tags, as: :tags, suggestions: { "Postgres" => "postgres database db sql" }
Submits ONE comma-joined param (user[tags] = "Ruby,Rails"), the primitive's
wire contract — the model splits it (an attribute :tags + a tags= writer,
or an ActiveModel array type).
This file is autoloaded ONLY when Phlex::Reactive is present (the Forms::Live gate in lib/phlex_forms.rb) because it includes ClientBindings at class level. The reactive_tags_* client helpers require phlex-reactive >= 0.11.4.
It uses the reactive_tags_add/option/remove helpers for the chip/query/option behavior, and the ROOT's wire attrs come from the 0.12.2 escape-hatch sugar: reactive_tags(name: @name) takes the per-instance wire name verbatim ("user") — the class-level reactive_scope compile can't express it — validated at render; reactive_filter(input: "#…_query") targets the query input by id so it never submits, and (unlike the old raw -input-only attr) also emits data-reactive-filter-option so the 0.12.x client type-ahead actually runs (issue #6 Caveats 1 & 2).
Direct Known Subclasses
Class Method Summary collapse
-
.query_id(id) ⇒ Object
The query input's id — the reactive_filter(input:) target and the id the search input itself carries.
Instance Method Summary collapse
-
#initialize(*modifiers, name:, id:, value: nil, suggestions: [], error: false, placeholder: "Add a tag…", **attributes) ⇒ TagField
constructor
A new instance of TagField.
- #view_template ⇒ Object
Constructor Details
#initialize(*modifiers, name:, id:, value: nil, suggestions: [], error: false, placeholder: "Add a tag…", **attributes) ⇒ TagField
Returns a new instance of TagField.
31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/forms/tag_field.rb', line 31 def initialize(*modifiers, name:, id:, value: nil, suggestions: [], error: false, placeholder: "Add a tag…", **attributes) @modifiers = modifiers @name = name # "user[tags]" — instance-dynamic @id = id @value = value.is_a?(Array) ? value.compact.join(",") : value.to_s @suggestions = normalize_suggestions(suggestions) @error = error @placeholder = placeholder @attributes = attributes super() end |
Class Method Details
.query_id(id) ⇒ Object
The query input's id — the reactive_filter(input:) target and the id the search input itself carries. Public so Forms::Live can derive the same id when it hoists the tag wire attrs onto the
56 |
# File 'lib/forms/tag_field.rb', line 56 def self.query_id(id) = "#{id}_query" |
Instance Method Details
#view_template ⇒ Object
44 45 46 47 48 49 50 51 |
# File 'lib/forms/tag_field.rb', line 44 def view_template # Standalone: THIS div is the reactive root. Inside a Forms::Live form the # widget renders rootless (Forms::RootlessTagField) — the outer <form> is # the root and carries these tag attrs — so the form owns the hidden field. div(**mix(reactive_root(id: "#{@id}_widget"), root_tag_attributes, class: root_classes)) do body end end |