class Formtastic::Inputs::CheckBoxesInput

A CheckBoxes input is used to render a series of checkboxes. This is an alternative input choice for `has_many` or `has_and_belongs_to_many` associations like a `Post` belonging to many `categories` (by default, a {SelectInput `:select`} input is used, allowing multiple selections).

Within the standard `<li>` wrapper, the output is a `<fieldset>` with a `<legend>` to represent the “label” for the input, and an `<ol>` containing `<li>`s for each choice in the association. Each `<li>` choice contains a hidden `<input>` tag for the “unchecked” value (like Rails), and a `<label>` containing the checkbox `<input>` and the label text for each choice.

@example Basic example with full form context

<%= semantic_form_for @post do |f| %>
  <%= f.inputs do %>
    <%= f.input :categories, :as => :check_boxes %>
  <% end %>
<% end %>

<li class='check_boxes'>
  <fieldset>
    <legend class="label"><label>Categories</label></legend>
    <ol>
      <li>
        <input type="hidden" name="post[category_ids][1]" value="">
        <label for="post_category_ids_1"><input id="post_category_ids_1" name="post[category_ids][1]" type="checkbox" value="1" /> Ruby</label>
      </li>
      <li>
        <input type="hidden" name="post[category_ids][2]" value="">
        <label for="post_category_ids_2"><input id="post_category_ids_2" name="post[category_ids][2]" type="checkbox" value="2" /> Rails</label>
      </li>
    </ol>
  </fieldset>
</li>

@example `:collection` can be used to customize the choices

<%= f.input :categories, :as => :check_boxes, :collection => @categories %>
<%= f.input :categories, :as => :check_boxes, :collection => Category.all %>
<%= f.input :categories, :as => :check_boxes, :collection => Category.some_named_scope %>
<%= f.input :categories, :as => :check_boxes, :collection => Category.pluck(:label, :id) %>
<%= f.input :categories, :as => :check_boxes, :collection => [Category.find_by_name("Ruby"), Category.find_by_name("Rails")] %>
<%= f.input :categories, :as => :check_boxes, :collection => ["Ruby", "Rails"] %>
<%= f.input :categories, :as => :check_boxes, :collection => [["Ruby", "ruby"], ["Rails", "rails"]] %>
<%= f.input :categories, :as => :check_boxes, :collection => [["Ruby", "1"], ["Rails", "2"]] %>
<%= f.input :categories, :as => :check_boxes, :collection => [["Ruby", 1], ["Rails", 2]] %>
<%= f.input :categories, :as => :check_boxes, :collection => [["Ruby", 1, {'data-attr' => 'attr-value'}]] %>
<%= f.input :categories, :as => :check_boxes, :collection => 1..5 %>
<%= f.input :categories, :as => :check_boxes, :collection => [:ruby, :rails] %>
<%= f.input :categories, :as => :check_boxes, :collection => [["Ruby", :ruby], ["Rails", :rails]] %>
<%= f.input :categories, :as => :check_boxes, :collection => Set.new([:ruby, :rails]) %>

@example `:hidden_fields` can be used to skip Rails' rendering of a hidden field before every checkbox

<%= f.input :categories, :as => :check_boxes, :hidden_fields => false %>

@example `:disabled` can be used to disable any checkboxes with a value found in the given Array

<%= f.input :categories, :as => :check_boxes, :collection => ["a", "b"], :disabled => ["a"] %>

@example `:value_as_class` can be used to add a class to the `<li>` wrapped around each choice using the checkbox value for custom styling of each choice

<%= f.input :categories, :as => :check_boxes, :value_as_class => true %>

@see Formtastic::Helpers::InputsHelper#input InputsHelper#input for full documentation of all possible options. @see Formtastic::Inputs::BooleanInput BooleanInput for a single checkbox for boolean (checked = true) inputs

@todo Do/can we support the per-item HTML options like RadioInput?

Public Instance Methods

check_box_with_hidden_input(choice) click to toggle source
# File lib/formtastic/inputs/check_boxes_input.rb, line 111
def check_box_with_hidden_input(choice)
  value = choice_value(choice)
  builder.check_box(
    association_primary_key || method,
    extra_html_options(choice).merge(:id => choice_input_dom_id(choice), :name => input_name, :disabled => disabled?(value), :required => false),
    value,
    unchecked_value
  )
end
check_box_without_hidden_input(choice) click to toggle source
# File lib/formtastic/inputs/check_boxes_input.rb, line 121
def check_box_without_hidden_input(choice)
  value = choice_value(choice)
  template.check_box_tag(
    input_name,
    value,
    checked?(value),
    extra_html_options(choice).merge(:id => choice_input_dom_id(choice), :disabled => disabled?(value), :required => false)
  )
end
checked?(value) click to toggle source
# File lib/formtastic/inputs/check_boxes_input.rb, line 135
def checked?(value)
  selected_values.include?(value)
end
choice_html(choice) click to toggle source
# File lib/formtastic/inputs/check_boxes_input.rb, line 88
def choice_html(choice)
  template.content_tag(
    :label,
    checkbox_input(choice) + choice_label(choice),
    label_html_options.merge(:for => choice_input_dom_id(choice), :class => nil)
  )
end
disabled?(value) click to toggle source
# File lib/formtastic/inputs/check_boxes_input.rb, line 139
def disabled?(value)
  disabled_values.include?(value)
end
disabled_values() click to toggle source
# File lib/formtastic/inputs/check_boxes_input.rb, line 147
def disabled_values
  vals = options[:disabled] || []
  vals = [vals] unless vals.is_a?(Array)
  vals
end
extra_html_options(choice) click to toggle source
# File lib/formtastic/inputs/check_boxes_input.rb, line 131
def extra_html_options(choice)
  input_html_options.merge(custom_choice_html_options(choice))
end
hidden_field_for_all() click to toggle source
# File lib/formtastic/inputs/check_boxes_input.rb, line 96
def hidden_field_for_all
  if hidden_fields?
    ''
  else
    options = {}
    options[:class] = [method.to_s.singularize, 'default'].join('_') if value_as_class?
    options[:id] = [object_name, method, 'none'].join('_')
    template.hidden_field_tag(input_name, '', options)
  end
end
hidden_fields?() click to toggle source
# File lib/formtastic/inputs/check_boxes_input.rb, line 107
def hidden_fields?
  options[:hidden_fields]
end
input_name() click to toggle source
# File lib/formtastic/inputs/check_boxes_input.rb, line 157
def input_name
  if builder.options.key?(:index)
    "#{object_name}[#{builder.options[:index]}][#{association_primary_key || method}][]"
  else
    "#{object_name}[#{association_primary_key || method}][]"
  end
end
selected_values() click to toggle source
# File lib/formtastic/inputs/check_boxes_input.rb, line 143
def selected_values
  @selected_values ||= make_selected_values
end
to_html() click to toggle source
# File lib/formtastic/inputs/check_boxes_input.rb, line 72
def to_html
  input_wrapping do
    choices_wrapping do
      legend_html <<
      hidden_field_for_all <<
      choices_group_wrapping do
        collection.map { |choice|
          choice_wrapping(choice_wrapping_html_options(choice)) do
            choice_html(choice)
          end
        }.join("\n").html_safe
      end
    end
  end
end
unchecked_value() click to toggle source
# File lib/formtastic/inputs/check_boxes_input.rb, line 153
def unchecked_value
  options[:unchecked_value] || ''
end

Protected Instance Methods

checkbox_input(choice) click to toggle source
# File lib/formtastic/inputs/check_boxes_input.rb, line 167
def checkbox_input(choice)
  if hidden_fields?
    check_box_with_hidden_input(choice)
  else
    check_box_without_hidden_input(choice)
  end
end
make_selected_values() click to toggle source
# File lib/formtastic/inputs/check_boxes_input.rb, line 175
def make_selected_values
  if object.respond_to?(method)
    selected_items = object.send(method)

    # Construct an array from the return value, regardless of the return type
    selected_items = [*selected_items].compact.flatten

    [*selected_items.map { |o| send_or_call_or_object(value_method, o) }].compact
  else
    []
  end
end