Class: Lotus::Helpers::FormHelper::FormBuilder

Inherits:
HtmlHelper::HtmlBuilder show all
Defined in:
lib/lotus/helpers/form_helper/form_builder.rb

Overview

Form builder

See Also:

Since:

  • x.x.x

Constant Summary collapse

BROWSER_METHODS =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Set of HTTP methods that are understood by web browsers

Since:

  • x.x.x

['GET', 'POST'].freeze
CHECKED =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Checked attribute value

See Also:

Since:

  • x.x.x

'checked'.freeze
SELECTED =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Selected attribute value for option

See Also:

Since:

  • x.x.x

'selected'.freeze
ACCEPT_SEPARATOR =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Separator for accept attribute of file input

See Also:

  • #file_input

Since:

  • x.x.x

','.freeze
INPUT_ID_REPLACEMENT =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Replacement for input id interpolation

See Also:

  • #_input_id

Since:

  • x.x.x

'-\k<token>'.freeze
INPUT_VALUE_REPLACEMENT =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Replacement for input value interpolation

See Also:

  • #_value

Since:

  • x.x.x

'.\k<token>'.freeze
DEFAULT_UNCHECKED_VALUE =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Default value for unchecked check box

See Also:

Since:

  • x.x.x

'0'.freeze
DEFAULT_CHECKED_VALUE =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Default value for checked check box

See Also:

Since:

  • x.x.x

'1'.freeze

Constants inherited from HtmlHelper::HtmlBuilder

HtmlHelper::HtmlBuilder::CONTENT_TAGS, HtmlHelper::HtmlBuilder::EMPTY_TAGS, HtmlHelper::HtmlBuilder::NEWLINE

Instance Method Summary collapse

Methods inherited from HtmlHelper::HtmlBuilder

#empty_tag, #method_missing, #nested?, #resolve, #tag

Constructor Details

#initialize(form, attributes, params, &blk) ⇒ Lotus::Helpers::FormHelper::FormBuilder #initialize(form, attributes, params, &blk) ⇒ Lotus::Helpers::FormHelper::FormBuilder

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Instantiate a form builder

Overloads:

  • #initialize(form, attributes, params, &blk) ⇒ Lotus::Helpers::FormHelper::FormBuilder

    Top level form

    Parameters:

    • form (Lotus::Helpers:FormHelper::Form)

      the form

    • attributes (::Hash)

      a set of HTML attributes

    • params (Lotus::Action::Params)

      request params

    • blk (Proc)

      a block that describes the contents of the form

  • #initialize(form, attributes, params, &blk) ⇒ Lotus::Helpers::FormHelper::FormBuilder

    Nested form

    Parameters:

    • form (Lotus::Helpers:FormHelper::Form)

      the form

    • attributes (Lotus::Helpers::FormHelper::Values)

      user defined values

    • blk (Proc)

      a block that describes the contents of the form

Since:

  • x.x.x



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/lotus/helpers/form_helper/form_builder.rb', line 101

def initialize(form, attributes, context = nil, &blk)
  super()

  @context = context
  @blk     = blk

  # Nested form
  if @context.nil? && attributes.is_a?(Values)
    @values     = attributes
    @attributes = {}
    @name       = form
  else
    @form       = form
    @name       = form.name
    @values     = Values.new(form.values, @context.params)
    @attributes = attributes
    @csrf_token = csrf_token
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Lotus::Helpers::HtmlHelper::HtmlBuilder

Instance Method Details

#check_box(name, attributes = {}) ⇒ Object

Check box

It renders a check box input.

When a form is submitted, browsers don’t send the value of unchecked check boxes. If an user unchecks a check box, their browser won’t send the unchecked value. On the server side the corresponding value is missing, so the application will assume that the user action never happened.

To solve this problem the form renders a hidden field with the “unchecked value”. When the user unchecks the input, the browser will ignore it, but it will still send the value of the hidden input. See the examples below.

When editing a resource, the form automatically assigns the checked="checked" attribute.

Examples:

Basic usage

<%=
  check_box :free_shipping
%>

# Output:
#  <input type="hidden" name="delivery[free_shipping]" value="0">
#  <input type="checkbox" name="delivery[free_shipping]" id="delivery-free-shipping" value="1">

Specify (un)checked values

<%=
  check_box :free_shipping, checked_value: 'true', unchecked_value: 'false'
%>

# Output:
#  <input type="hidden" name="delivery[free_shipping]" value="false">
#  <input type="checkbox" name="delivery[free_shipping]" id="delivery-free-shipping" value="true">

Automatic “checked” attribute

# For this example the params are:
#
#  { delivery: { free_shipping: '1' } }
<%=
  check_box :free_shipping
%>

# Output:
#  <input type="hidden" name="delivery[free_shipping]" value="0">
#  <input type="checkbox" name="delivery[free_shipping]" id="delivery-free-shipping" value="1" checked="checked">

Force “checked” attribute

# For this example the params are:
#
#  { delivery: { free_shipping: '0' } }
<%=
  check_box :free_shipping, checked: 'checked'
%>

# Output:
#  <input type="hidden" name="delivery[free_shipping]" value="0">
#  <input type="checkbox" name="delivery[free_shipping]" id="delivery-free-shipping" value="1" checked="checked">

Multiple check boxes

<%=
  check_box :languages, name: 'book[languages][]', value: 'italian', id: nil
  check_box :languages, name: 'book[languages][]', value: 'english', id: nil
%>

# Output:
#  <input type="checkbox" name="book[languages][]" value="italian">
#  <input type="checkbox" name="book[languages][]" value="english">

Automatic “checked” attribute for multiple check boxes

# For this example the params are:
#
#  { book: { languages: ['italian'] } }
<%=
  check_box :languages, name: 'book[languages][]', value: 'italian', id: nil
  check_box :languages, name: 'book[languages][]', value: 'english', id: nil
%>

# Output:
#  <input type="checkbox" name="book[languages][]" value="italian" checked="checked">
#  <input type="checkbox" name="book[languages][]" value="english">

Parameters:

  • name (Symbol)

    the input name

  • attributes (Hash) (defaults to: {})

    HTML attributes to pass to the input tag

Options Hash (attributes):

  • :checked_value (String) — default: defaults to "1"
  • :unchecked_value (String) — default: defaults to "0"

Since:

  • x.x.x



342
343
344
345
# File 'lib/lotus/helpers/form_helper/form_builder.rb', line 342

def check_box(name, attributes = {})
  _hidden_field_for_check_box(    name, attributes)
  input _attributes_for_check_box(name, attributes)
end

#color_field(name, attributes = {}) ⇒ Object

Color input

Examples:

Basic usage

<%=
  # ...
  color_field :background
%>

# Output:
#  <input type="color" name="user[background]" id="user-background" value="">

Parameters:

  • name (Symbol)

    the input name

  • attributes (Hash) (defaults to: {})

    HTML attributes to pass to the input tag

Since:

  • x.x.x



362
363
364
# File 'lib/lotus/helpers/form_helper/form_builder.rb', line 362

def color_field(name, attributes = {})
  input _attributes(:color, name, attributes)
end

#date_field(name, attributes = {}) ⇒ Object

Date input

Examples:

Basic usage

<%=
  # ...
  date_field :birth_date
%>

# Output:
#  <input type="date" name="user[birth_date]" id="user-birth-date" value="">

Parameters:

  • name (Symbol)

    the input name

  • attributes (Hash) (defaults to: {})

    HTML attributes to pass to the input tag

Since:

  • x.x.x



381
382
383
# File 'lib/lotus/helpers/form_helper/form_builder.rb', line 381

def date_field(name, attributes = {})
  input _attributes(:date, name, attributes)
end

#datetime_field(name, attributes = {}) ⇒ Object

Datetime input

Examples:

Basic usage

<%=
  # ...
  datetime_field :delivered_at
%>

# Output:
#  <input type="datetime" name="delivery[delivered_at]" id="delivery-delivered-at" value="">

Parameters:

  • name (Symbol)

    the input name

  • attributes (Hash) (defaults to: {})

    HTML attributes to pass to the input tag

Since:

  • x.x.x



400
401
402
# File 'lib/lotus/helpers/form_helper/form_builder.rb', line 400

def datetime_field(name, attributes = {})
  input _attributes(:datetime, name, attributes)
end

#datetime_local_field(name, attributes = {}) ⇒ Object

Datetime Local input

Examples:

Basic usage

<%=
  # ...
  datetime_local_field :delivered_at
%>

# Output:
#  <input type="datetime-local" name="delivery[delivered_at]" id="delivery-delivered-at" value="">

Parameters:

  • name (Symbol)

    the input name

  • attributes (Hash) (defaults to: {})

    HTML attributes to pass to the input tag

Since:

  • x.x.x



419
420
421
# File 'lib/lotus/helpers/form_helper/form_builder.rb', line 419

def datetime_local_field(name, attributes = {})
  input _attributes(:'datetime-local', name, attributes)
end

#email_field(name, attributes = {}) ⇒ Object

Email input

Examples:

Basic usage

<%=
  # ...
  email_field :email
%>

# Output:
#  <input type="email" name="user[email]" id="user-email" value="">

Parameters:

  • name (Symbol)

    the input name

  • attributes (Hash) (defaults to: {})

    HTML attributes to pass to the input tag

Since:

  • x.x.x



438
439
440
# File 'lib/lotus/helpers/form_helper/form_builder.rb', line 438

def email_field(name, attributes = {})
  input _attributes(:email, name, attributes)
end

#fields_for(name) ⇒ Object

Nested fields

The inputs generated by the wrapped block will be prefixed with the given name It supports infinite levels of nesting.

Examples:

Basic usage

<%=
  form_for :delivery, routes.deliveries_path do
    text_field :customer_name

    fields_for :address do
      text_field :street
    end

    submit 'Create'
  end
%>

Output:
  # <form action="/deliveries" method="POST" accept-charset="utf-8" id="delivery-form">
  #   <input type="text" name="delivery[customer_name]" id="delivery-customer-name" value="">
  #   <input type="text" name="delivery[address][street]" id="delivery-address-street" value="">
  #
  #   <button type="submit">Create</button>
  # </form>

Multiple levels of nesting

<%=
  form_for :delivery, routes.deliveries_path do
    text_field :customer_name

    fields_for :address do
      text_field :street

      fields_for :location do
        text_field :city
        text_field :country
      end
    end

    submit 'Create'
  end
%>

Output:
  # <form action="/deliveries" method="POST" accept-charset="utf-8" id="delivery-form">
  #   <input type="text" name="delivery[customer_name]" id="delivery-customer-name" value="">
  #   <input type="text" name="delivery[address][street]" id="delivery-address-street" value="">
  #   <input type="text" name="delivery[address][location][city]" id="delivery-address-location-city" value="">
  #   <input type="text" name="delivery[address][location][country]" id="delivery-address-location-country" value="">
  #
  #   <button type="submit">Create</button>
  # </form>

Parameters:

  • name (Symbol)

    the nested name, it’s used to generate input names, ids, and to lookup params to fill values.

Since:

  • x.x.x



197
198
199
200
201
202
203
# File 'lib/lotus/helpers/form_helper/form_builder.rb', line 197

def fields_for(name)
  current_name = @name
  @name        = _input_name(name)
  yield
ensure
  @name = current_name
end

#file_field(name, attributes = {}) ⇒ Object

File input

PLEASE REMEMBER TO ADD enctype: 'multipart/form-data' ATTRIBUTE TO THE FORM

Examples:

Basic usage

<%=
  # ...
  file_field :avatar
%>

# Output:
#  <input type="file" name="user[avatar]" id="user-avatar">

Accepted mime types

<%=
  # ...
  file_field :resume, accept: 'application/pdf,application/ms-word'
%>

# Output:
#  <input type="file" name="user[resume]" id="user-resume" accept="application/pdf,application/ms-word">

Accepted mime types (as array)

<%=
  # ...
  file_field :resume, accept: ['application/pdf', 'application/ms-word']
%>

# Output:
#  <input type="file" name="user[resume]" id="user-resume" accept="application/pdf,application/ms-word">

Parameters:

  • name (Symbol)

    the input name

  • attributes (Hash) (defaults to: {})

    HTML attributes to pass to the input tag

Options Hash (attributes):

  • :accept (String, Array)

    Optional set of accepted MIME Types

Since:

  • x.x.x



497
498
499
500
501
502
# File 'lib/lotus/helpers/form_helper/form_builder.rb', line 497

def file_field(name, attributes = {})
  attributes[:accept] = Array(attributes[:accept]).join(ACCEPT_SEPARATOR) if attributes.key?(:accept)
  attributes = { type: :file, name: _input_name(name), id: _input_id(name) }.merge(attributes)

  input(attributes)
end

#hidden_field(name, attributes = {}) ⇒ Object

Hidden input

Examples:

Basic usage

<%=
  # ...
  hidden_field :customer_id
%>

# Output:
#  <input type="hidden" name="delivery[customer_id]" id="delivery-customer-id" value="">

Parameters:

  • name (Symbol)

    the input name

  • attributes (Hash) (defaults to: {})

    HTML attributes to pass to the input tag

Since:

  • x.x.x



457
458
459
# File 'lib/lotus/helpers/form_helper/form_builder.rb', line 457

def hidden_field(name, attributes = {})
  input _attributes(:hidden, name, attributes)
end

#label(content, attributes = {}) ⇒ Object

Label tag

The first param content can be a Symbol that represents the target field (Eg. :extended_title), or a String which is used as it is.

# Output:
#  <label for="book-extended-title">Extended Title</label>

# Output:
#  <label for="book-extended-title">Title</label>

# Output:
#  <label for="delivery-address-city">City</label>
#  <input type="text" name="delivery[address][city] id="delivery-address-city" value="">

Examples:

Basic usage

<%=
  # ...
  label :extended_title
%>

Custom content

<%=
  # ...
  label 'Title', for: :extended_title
%>

Nested fields usage

<%=
  # ...
  fields_for :address do
    label :city
    text_field :city
  end
%>

Parameters:

  • content (Symbol, String)

    the field name or a content string

  • attributes (Hash) (defaults to: {})

    HTML attributes to pass to the label tag

Since:

  • x.x.x



246
247
248
249
250
251
# File 'lib/lotus/helpers/form_helper/form_builder.rb', line 246

def label(content, attributes = {})
  attributes = { for: _for(content, attributes.delete(:for)) }.merge(attributes)
  content    = Utils::String.new(content).titleize

  super(content, attributes)
end

#password_field(name, attributes = {}) ⇒ Object

Password input

Examples:

Basic usage

<%=
  # ...
  password_field :password
%>

# Output:
#  <input type="password" name="signup[password]" id="signup-password" value="">

Parameters:

  • name (Symbol)

    the input name

  • attributes (Hash) (defaults to: {})

    HTML attributes to pass to the input tag

Since:

  • x.x.x



584
585
586
# File 'lib/lotus/helpers/form_helper/form_builder.rb', line 584

def password_field(name, attributes = {})
  input({ type: :password, name: _input_name(name), id: _input_id(name), value: nil }.merge(attributes))
end

#radio_button(name, value, attributes = {}) ⇒ Object

Radio input

If request params have a value that corresponds to the given value, it automatically sets the checked attribute. This Lotus::Controller integration happens without any developer intervention.

Examples:

Basic usage

<%=
  # ...
  radio_button :category, 'Fiction'
  radio_button :category, 'Non-Fiction'
%>

# Output:
#  <input type="radio" name="book[category]" value="Fiction">
#  <input type="radio" name="book[category]" value="Non-Fiction">

Automatic checked value

# Given the following params:
#
# book: {
#   category: 'Non-Fiction'
# }

<%=
  # ...
  radio_button :category, 'Fiction'
  radio_button :category, 'Non-Fiction'
%>

# Output:
#  <input type="radio" name="book[category]" value="Fiction">
#  <input type="radio" name="book[category]" value="Non-Fiction" checked="checked">

Parameters:

  • name (Symbol)

    the input name

  • value (String)

    the input value

  • attributes (Hash) (defaults to: {})

    HTML attributes to pass to the input tag

Since:

  • x.x.x



563
564
565
566
567
# File 'lib/lotus/helpers/form_helper/form_builder.rb', line 563

def radio_button(name, value, attributes = {})
  attributes = { type: :radio, name: _input_name(name), value: value }.merge(attributes)
  attributes[:checked] = CHECKED if _value(name) == value
  input(attributes)
end

#select(name, values, attributes = {}) ⇒ Object

Select input

If request params have a value that corresponds to one of the given values, it automatically sets the selected attribute on the <option> tag. This Lotus::Controller integration happens without any developer intervention.

Examples:

Basic usage

<%=
  # ...
  values = Hash['it' => 'Italy', 'us' => 'United States']
  select :stores, values
%>

# Output:
#  <select name="book[store]" id="book-store">
#    <option value="it">Italy</option>
#    <option value="us">United States</option>
#  </select>

Automatic selected option

# Given the following params:
#
# book: {
#   store: 'it'
# }

<%=
  # ...
  values = Hash['it' => 'Italy', 'us' => 'United States']
  select :stores, values
%>

# Output:
#  <select name="book[store]" id="book-store">
#    <option value="it" selected="selected">Italy</option>
#    <option value="us">United States</option>
#  </select>

Parameters:

  • name (Symbol)

    the input name

  • values (Hash)

    a Hash to generate <option> tags. Keys correspond to value and values correspond to the content.

  • attributes (Hash) (defaults to: {})

    HTML attributes to pass to the input tag

Since:

  • x.x.x



632
633
634
635
636
637
638
639
640
641
642
643
644
645
# File 'lib/lotus/helpers/form_helper/form_builder.rb', line 632

def select(name, values, attributes = {})
  options    = attributes.delete(:options) || {}
  attributes = { name: _input_name(name), id: _input_id(name) }.merge(attributes)

  super(attributes) do
    values.each do |value, content|
      if _value(name) == value
        option(content, {value: value, selected: SELECTED}.merge(options))
      else
        option(content, {value: value}.merge(options))
      end
    end
  end
end

#submit(content, attributes = {}) ⇒ Object

Submit button

Examples:

Basic usage

<%=
  # ...
  submit 'Create'
%>

# Output:
#  <button type="submit">Create</button>

Parameters:

  • content (String)

    The content

  • attributes (Hash) (defaults to: {})

    HTML attributes to pass to the button tag

Since:

  • x.x.x



662
663
664
665
# File 'lib/lotus/helpers/form_helper/form_builder.rb', line 662

def submit(content, attributes = {})
  attributes = { type: :submit }.merge(attributes)
  button(content, attributes)
end

#text_field(name, attributes = {}) ⇒ Object Also known as: input_text

Text input

Examples:

Basic usage

<%=
  # ...
  text_field :first_name
%>

# Output:
#  <input type="text" name="user[first_name]" id="user-first-name" value="">

Parameters:

  • name (Symbol)

    the input name

  • attributes (Hash) (defaults to: {})

    HTML attributes to pass to the input tag

Since:

  • x.x.x



519
520
521
# File 'lib/lotus/helpers/form_helper/form_builder.rb', line 519

def text_field(name, attributes = {})
  input _attributes(:text, name, attributes)
end

#to_sLotus::Utils::Escape::SafeString

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Resolves all the nodes and generates the markup

Returns:

  • (Lotus::Utils::Escape::SafeString)

    the output

See Also:

Since:

  • x.x.x



130
131
132
133
134
135
136
137
# File 'lib/lotus/helpers/form_helper/form_builder.rb', line 130

def to_s
  if toplevel?
    _method_override!
    form(@blk, @attributes)
  end

  super
end