Class: Forms::Base
Overview
Declarative form classes: subclass, declare the fields in #fields, render.
Inside #fields, self IS the form — the whole builder surface (field, row,
group, Input, submit, fields_for, ...) is available as bare calls.
class UserForm < Forms::Base
:spaced
def fields
field :email
row { field :first_name; field :last_name }
submit :primary
end
end
render UserForm.new(model: @user)
A render-time block appends after the declared fields:
render UserForm.new(model: @user) { |f| f.Hidden(:token) }
Constant Summary
Constants included from PhlexForms::Builder
PhlexForms::Builder::INPUT_TYPE_INFERENCE, PhlexForms::Builder::INPUT_TYPE_MODIFIERS
Instance Attribute Summary
Attributes inherited from Form
#errors, #method, #model, #scope, #theme, #url, #validate
Class Method Summary collapse
- .form_defaults ⇒ Object
- .form_modifiers ⇒ Object
-
.form_options(*modifiers, **defaults) ⇒ Object
Class-level defaults, inherited and merged down the subclass chain (instance args beat class defaults; subclass defaults beat parents'):.
-
.live(model:, scope: nil, debounce: 300) ⇒ Object
Server-truth live validation via phlex-reactive (a soft dependency):.
-
.reactive_available? ⇒ Boolean
Extracted so specs can exercise the FeatureUnavailable guard.
Instance Method Summary collapse
-
#fields ⇒ Object
The hook name
fieldsis verified free against Phlex::HTML (phlex 2.4.x) and this gem (Form defines fields_for/field_object, never fields). -
#initialize(*modifiers, **options) ⇒ Base
constructor
A new instance of Base.
-
#view_template ⇒ Object
Renders Form's chrome (action/method/CSRF/enctype), then the declared fields.
Methods inherited from Form
#collection_check_boxes, #collection_select, #default_field_variants, #field_id, #field_name, #field_object, #field_value, #fields_for, #rich_textarea, #submit, #time_zone_select, #validations_introspector
Methods included from PhlexForms::Builder
#Checkbox, #Control, #FileInput, #Hidden, #Input, #Label, #Radio, #Select, #Textarea, #Toggle, #field, #group, #row
Constructor Details
#initialize(*modifiers, **options) ⇒ Base
Returns a new instance of Base.
80 81 82 |
# File 'lib/forms/base.rb', line 80 def initialize(*modifiers, **) super(*(self.class.form_modifiers + modifiers).uniq, **self.class.form_defaults.merge()) end |
Class Method Details
.form_defaults ⇒ Object
39 40 41 42 |
# File 'lib/forms/base.rb', line 39 def form_defaults inherited = superclass.respond_to?(:form_defaults) ? superclass.form_defaults : {} inherited.merge(@form_defaults || {}) end |
.form_modifiers ⇒ Object
34 35 36 37 |
# File 'lib/forms/base.rb', line 34 def form_modifiers inherited = superclass.respond_to?(:form_modifiers) ? superclass.form_modifiers : [] (inherited + (@form_modifiers || [])).uniq end |
.form_options(*modifiers, **defaults) ⇒ Object
Class-level defaults, inherited and merged down the subclass chain (instance args beat class defaults; subclass defaults beat parents'):
:spaced, url: "/signup", validate: true
29 30 31 32 |
# File 'lib/forms/base.rb', line 29 def (*modifiers, **defaults) @form_modifiers = modifiers @form_defaults = defaults end |
.live(model:, scope: nil, debounce: 300) ⇒ Object
Server-truth live validation via phlex-reactive (a soft dependency):
class UserForm < Forms::Base
live model: User
def fields = field(:email)
end
Blur/debounced input POST every field to a :validate action that runs the REAL model validators and morphs the errors back in, focus intact. Only Forms::Base subclasses can be live — the endpoint rebuilds the form from its class; an inline block cannot be serialized.
55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/forms/base.rb', line 55 def live(model:, scope: nil, debounce: 300) unless reactive_available? raise PhlexForms::FeatureUnavailable, "#{name || 'this form'} declares `live` but the phlex-reactive gem is not " \ "installed. Add `gem \"phlex-reactive\"` to your Gemfile, or use " \ "`validate: true` for the client-side Stimulus mirror instead." end include Forms::Live setup_live(model_class: model, scope: scope || derive_live_scope(model), debounce:) end |
.reactive_available? ⇒ Boolean
Extracted so specs can exercise the FeatureUnavailable guard.
69 70 71 |
# File 'lib/forms/base.rb', line 69 def reactive_available? defined?(Phlex::Reactive::Component) ? true : false end |
Instance Method Details
#fields ⇒ Object
The hook name fields is verified free against Phlex::HTML (phlex 2.4.x)
and this gem (Form defines fields_for/field_object, never fields).
96 97 98 |
# File 'lib/forms/base.rb', line 96 def fields raise NotImplementedError, "#{self.class} must define #fields" end |
#view_template ⇒ Object
Renders Form's chrome (action/method/CSRF/enctype), then the declared
fields. yield/block_given? inside the inner block bind to
view_template's own block — the optional render-time block.
87 88 89 90 91 92 |
# File 'lib/forms/base.rb', line 87 def view_template super do fields yield self if block_given? end end |