Module: PhlexForms::Builder
- Included in:
- Forms::FieldsForBuilder, Forms::Form
- Defined in:
- lib/phlex_forms/builder.rb
Overview
The shared form-builder surface, included by Forms::Form, Forms::Field, and Forms::FieldsForBuilder so the three no longer copy-paste the API three times.
Two layers:
* The Control-first primary verb `field` — renders label + input +
error/hint in one call, inferring the input type and the `required` flag
from the model.
* Lower-level escape hatches (`Input`, `Select`, `Textarea`, `Checkbox`,
`Toggle`, `FileInput`, `Hidden`, `Label`, `Control`, `submit`) with the
same signatures they had before extraction, for when a caller needs full
control (custom Stimulus wiring, bespoke layout, ...).
Hosts mix this in and provide: render, model, scope, errors, and a
field(name)-style field_object that returns a Forms::Field for a name.
Constant Summary collapse
- INPUT_TYPE_MODIFIERS =
Positional symbols that name an input type (so
f.Input(:x, :email)works). %i[ text email password tel url search number date time datetime color range file hidden month week ].freeze
- INPUT_TYPE_INFERENCE =
Attribute-name -> input type inference. One canonical map (previously duplicated and divergent across Form and Field).
{ email: :email, password: :password, password_confirmation: :password, current_password: :password, new_password: :password, new_password_confirmation: :password, phone: :tel, telephone: :tel, tel: :tel, mobile: :tel, url: :url, website: :url, homepage: :url, search: :search, query: :search, date: :date, birthday: :date, birthdate: :date, born_on: :date, started_at: :date, ended_at: :date, time: :time, datetime: :datetime, timestamp: :datetime, color: :color, colour: :color }.freeze
Instance Method Summary collapse
- #Checkbox(name, *modifiers, **options) ⇒ Object
- #Control(name) ⇒ Object
-
#field(name, *modifiers, label: nil, hint: nil, as: nil, required: nil, choices: nil, **options) ⇒ Object
Render a complete field: label + control-wrapped input + error/hint.
- #FileInput(name, *modifiers, **options) ⇒ Object
- #Hidden(name) ⇒ Object
-
#Input(name, *modifiers, **options) ⇒ Object
------------------------------------------------------------------ Escape-hatch component API (stable signatures) ------------------------------------------------------------------.
- #Label(name, text = nil, *modifiers) ⇒ Object
- #Radio(name, value, *modifiers) ⇒ Object
- #Select(name, *modifiers, choices: nil, **options) ⇒ Object
- #Textarea(name, *modifiers, **options) ⇒ Object
- #Toggle(name, *modifiers, **options) ⇒ Object
Instance Method Details
#Checkbox(name, *modifiers, **options) ⇒ Object
99 100 101 102 |
# File 'lib/phlex_forms/builder.rb', line 99 def Checkbox(name, *modifiers, **) fo = field_object(name) render fo.checkbox(*modifiers, **fo.apply_validations()) end |
#Control(name) ⇒ Object
126 127 128 |
# File 'lib/phlex_forms/builder.rb', line 126 def Control(name, **, &) render field_object(name).control(**, &) end |
#field(name, *modifiers, label: nil, hint: nil, as: nil, required: nil, choices: nil, **options) ⇒ Object
Render a complete field: label + control-wrapped input + error/hint.
f.field :email # type=email, label auto, required inferred
f.field :role, as: :select, choices: roles
f.field :bio, as: :textarea, rows: 6
f.field :accept, as: :toggle
f.field :name, :primary, label: "Full name", hint: "As on your ID"
Options:
label: label text (defaults to the model's humanized attribute name;
pass false to omit the label)
hint: help text shown when there is no error
as: override the rendered control (:select, :textarea, :toggle,
:checkbox, :file, :hidden, and text-like types)
required: force the required flag (otherwise inferred from validations)
choices: choices for :select
Remaining positional modifiers/keywords pass through to the inner input.
65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/phlex_forms/builder.rb', line 65 def field(name, *modifiers, label: nil, hint: nil, as: nil, required: nil, choices: nil, **) fo = field_object(name) req = required.nil? ? fo.required? : required label_text = label == false ? nil : (label || fo.field_label) = fo.apply_validations() render fo.control(label: label_text, hint:, required: req) do render_field_input(fo, name, as, modifiers, choices:, required: req, **) end end |
#FileInput(name, *modifiers, **options) ⇒ Object
113 114 115 116 |
# File 'lib/phlex_forms/builder.rb', line 113 def FileInput(name, *modifiers, **) fo = field_object(name) render fo.file(*modifiers, **fo.apply_validations()) end |
#Hidden(name) ⇒ Object
118 119 120 |
# File 'lib/phlex_forms/builder.rb', line 118 def Hidden(name, **) render field_object(name).hidden(**) end |
#Input(name, *modifiers, **options) ⇒ Object
Escape-hatch component API (stable signatures)
81 82 83 84 85 86 87 |
# File 'lib/phlex_forms/builder.rb', line 81 def Input(name, *modifiers, **) fo = field_object(name) type = resolve_input_type(name, modifiers) type = :"datetime-local" if type == :datetime remaining = modifiers - INPUT_TYPE_MODIFIERS render fo.input(*remaining, type:, **fo.apply_validations()) end |
#Label(name, text = nil, *modifiers) ⇒ Object
122 123 124 |
# File 'lib/phlex_forms/builder.rb', line 122 def Label(name, text = nil, *modifiers, **, &) render field_object(name).label(text, *modifiers, **, &) end |
#Radio(name, value, *modifiers) ⇒ Object
104 105 106 |
# File 'lib/phlex_forms/builder.rb', line 104 def Radio(name, value, *modifiers, **) render field_object(name).radio(value, *modifiers, **) end |
#Select(name, *modifiers, choices: nil, **options) ⇒ Object
89 90 91 92 |
# File 'lib/phlex_forms/builder.rb', line 89 def Select(name, *modifiers, choices: nil, **) fo = field_object(name) render fo.choices_select(choices, *modifiers, **fo.apply_validations()) end |
#Textarea(name, *modifiers, **options) ⇒ Object
94 95 96 97 |
# File 'lib/phlex_forms/builder.rb', line 94 def Textarea(name, *modifiers, **) fo = field_object(name) render fo.textarea(*modifiers, **fo.apply_validations()) end |
#Toggle(name, *modifiers, **options) ⇒ Object
108 109 110 111 |
# File 'lib/phlex_forms/builder.rb', line 108 def Toggle(name, *modifiers, **) fo = field_object(name) render fo.toggle(*modifiers, **fo.apply_validations()) end |