Class: Proscenium::UI::Form

Inherits:
Component show all
Extended by:
ActiveSupport::Autoload, Literal::Properties
Includes:
FieldMethods, Translation
Defined in:
lib/proscenium/ui/form.rb,
lib/proscenium/ui/form/field_methods.rb

Overview

Helpers to aid in building forms and associated inputs with built-in styling, and inspired by Rails form helpers and SimpleForm.

Start by creating the form with ‘Proscenium::UI::Form`, which expects a model instance, and a block in which you define one or more fields. It automatically includes a hidden authenticity token field for you.

Example:

render Proscenium::UI::Form.new(User.new) do |f|
  f.text_field :name
  f.radio_group :role, %i[admin manager]
  f.submit 'Save'
end

The following fields (inputs) are available:

- `url_field` - <input> with 'url' type.
- `text_field` - <input> with 'text' type.
- `textarea_field` - <textarea>.
- `rich_textarea_field` - A rich <textarea> using ActionText and Trix.
- `email_field` - <input> with 'email' type.
- `number_field` - <input> with 'number' type.
- `color_field` - <input> with 'color' type.
- `hidden_field` - <input> with 'hidden' type.
- `search_field` - <input> with 'search' type.
- `password_field` - <input> with 'password' type.
- `tel_field` - <input> with 'tel' type.
- `range_field` - <input> with 'range' type.
- `time_field` - <input> with 'time' type.
- `date_field` - <input> with 'date' type.
- `week_field` - <input> with 'week' type.
- `month_field` - <input> with 'month' type.
- `datetime_local_field` - <input> with 'datetime-local' type.
- `checkbox_field` - <input> with 'checkbox' type.
- `radio_field` - <input> with 'radio' type.
- `radio_group` - group of <input>'s with 'radio' type.
- `select_field` - <select> input.

Defined Under Namespace

Modules: FieldMethods, Fields, Translation

Constant Summary collapse

STANDARD_METHOD_VERBS =
%w[get post].freeze

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Translation

#translate, #translate_label

Methods included from FieldMethods

#checkbox_field, #datetime_local_field, #hidden_field, #radio_field, #radio_group, #radio_input, #rich_textarea_field, #select_country_field, #select_field, #tel_field, #textarea_field

Methods inherited from Phlex

inherited, sideload_assets

Methods included from Phlex::AssetInclusions

#include_assets, #include_javascripts, #include_stylesheets

Methods included from Phlex::CssModules

#after_template, #before_template, included, #process_attributes

Methods included from CssModule

#class_names, #css_module

Methods included from SourcePath

included

Class Method Details

.input_field(method_name, type:) ⇒ Object



72
73
74
75
76
77
# File 'lib/proscenium/ui/form.rb', line 72

def self.input_field(method_name, type:)
  define_method method_name do |*args, **attributes|
    merge_bang_attributes! args, attributes
    render Fields::Input.new(args, @model, self, type:, **attributes)
  end
end

Instance Method Details

#actionObject



178
179
180
# File 'lib/proscenium/ui/form.rb', line 178

def action
  @_view_context.url_for(@action || @model)
end

#authenticity_token_fieldObject



167
168
169
170
171
172
173
174
175
176
# File 'lib/proscenium/ui/form.rb', line 167

def authenticity_token_field
  return if method == 'get'

  input(
    name: 'authenticity_token',
    type: 'hidden',
    value: @_view_context.form_authenticity_token(form_options: { action:,
                                                                  method: @method })
  )
end

#error(message: nil, attribute: nil, &content) ⇒ Object

Returns a <div> with the given ‘message` as its content. If `message` is not given, and `attribute` is, then first error message for the given model `attribute`.

Parameters:

  • message (String) (defaults to: nil)

    error message to display.

  • attribute (Symbol) (defaults to: nil)

    name of the model attribute.



122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/proscenium/ui/form.rb', line 122

def error(message: nil, attribute: nil, &content)
  if message.nil? && attribute.nil? && !content
    raise ArgumentError, 'One of `message:`, `attribute:` or a block is required'
  end

  if content
    div class: :@error, &content
  else
    div class: :@error do
      message || @model.errors[attribute]&.first
    end
  end
end

#error_for_baseObject



145
146
147
148
149
150
151
152
# File 'lib/proscenium/ui/form.rb', line 145

def error_for_base
  return unless @model.errors.key?(:base)

  callout :danger do |x|
    x.title { 'Unable to save...' }
    div { @model.errors.full_messages_for(:base).first }
  end
end

#field_idObject



163
164
165
# File 'lib/proscenium/ui/form.rb', line 163

def field_id(*)
  @_view_context.field_id(ActiveModel::Naming.param_key(@model.class), *)
end

#field_name(*names, multiple: false) ⇒ Object



154
155
156
157
158
159
160
161
# File 'lib/proscenium/ui/form.rb', line 154

def field_name(*names, multiple: false)
  # Delete the `?` suffix if present.
  lname = names.pop.to_s
  names.append lname.delete_suffix('?').to_sym

  @_view_context.field_name(ActiveModel::Naming.param_key(@model.class), *names,
                            multiple:)
end

#methodObject



188
189
190
# File 'lib/proscenium/ui/form.rb', line 188

def method
  STANDARD_METHOD_VERBS.include?(@method) ? @method : 'post'
end

#method_fieldObject



182
183
184
185
186
# File 'lib/proscenium/ui/form.rb', line 182

def method_field
  return if STANDARD_METHOD_VERBS.include?(@method)

  input type: 'hidden', name: '_method', value: @method, autocomplete: 'off'
end

#submit(value = 'Save') ⇒ Object

Returns a button with type of ‘submit’, using the ‘value` given.

Parameters:

  • value (String) (defaults to: 'Save')

    Value of the ‘value` attribute.



113
114
115
# File 'lib/proscenium/ui/form.rb', line 113

def submit(value = 'Save', **)
  input(name: 'commit', type: :submit, value:, **)
end

#use_field(field_class, *args, **attributes) ⇒ Object

Use the given ‘field_class` to render a custom field. This allows you to create a custom form field on an as-needed basis. The `field_class` must be a subclass of `Proscenium::UI::Form::Fields::Base`.

Example:

render Proscenium::UI::Form.new @resource do |f|
  f.use_field Administrator::EmailField, :email, :required!
end

Parameters:

  • field_class (Class<Proscenium::UI::Form::Fields::Base>)
  • args (Array<Symbol>)

    name or nested names of model attribute

  • attributes (Hash)

    passed through to each input



105
106
107
108
# File 'lib/proscenium/ui/form.rb', line 105

def use_field(field_class, *args, **attributes)
  merge_bang_attributes! args, attributes
  render field_class.new(args, model, self, **attributes)
end

#view_template(&block) ⇒ Object



136
137
138
139
140
141
142
143
# File 'lib/proscenium/ui/form.rb', line 136

def view_template(&block)
  form action:, method:, **@attributes do
    method_field
    authenticity_token_field
    error_for_base
    yield_content(&block)
  end
end