Custom inputs examples

Daniel Powell edited this page Jan 11, 2017 · 7 revisions

Custom inputs examples

Week Day Input

In order to get an input with localized week days:

# app/inputs/wday_input.rb
class WdayInput < SimpleForm::Inputs::Base
  def input
    @builder.select(attribute_name, I18n.t(:"date.day_names").each_with_index.to_a)
  end
end

Then, use it in your form:

<%= timetable.input :wday, :as => :wday %>

Date Time Picker for Twitter Bootstrap 3 using the DateTimePicker JS Library

## app/inputs/date_time_picker_input.rb
class DateTimePickerInput < SimpleForm::Inputs::Base
  def input
    template.content_tag(:div, class: 'input-group date form_datetime') do
      template.concat @builder.text_field(attribute_name, input_html_options)
      template.concat span_remove
      template.concat span_table
    end
  end

  def input_html_options
    super.merge({class: 'form-control', readonly: true})
  end

  def span_remove
    template.content_tag(:span, class: 'input-group-addon') do
      template.concat icon_remove
    end
  end

  def span_table
    template.content_tag(:span, class: 'input-group-addon') do
      template.concat icon_table
    end
  end

  def icon_remove
    "<i class='glyphicon glyphicon-remove'></i>".html_safe
  end

  def icon_table
    "<i class='glyphicon glyphicon-th'></i>".html_safe
  end

end

To use add this to an appropriate coffee script file

$(document).ready ->
  $('.form_datetime').datetimepicker({
    autoclose: true,
    todayBtn: true,
    pickerPosition: "bottom-left",
    format: 'mm-dd-yyyy hh:ii'
  });

call on simple form input with

f.input :my_date, as: :date_time_picker

Between inputs

This example uses MetaSearch which is now deprecated but still provides a good example of custom inputs. This input actually generates two input fields, one for the lower boundary (greater than or equal to) and one for the upper (less than or equal to). For example, searching for users between the ages of 21 and 30.

# app/inputs/between_input.rb
class BetweenInput < SimpleForm::Inputs::Base
  def input
    field1 = @builder.number_field(:"#{attribute_name}_gteq", input_html_options)
    field2 = @builder.number_field(:"#{attribute_name}_lteq", input_html_options)

    # Be aware for I18n: translate the "and" here
    (field1 << @builder.label(:"#{attribute_name}_lteq", 'and', class: 'separator') << field2).html_safe
  end

  # Make the label be for the first of the two fields
  def label_target
    :"#{attribute_name}_gteq"
  end
end
- # app/views/users/_search.html.haml
= simple_form_for @user_search do |form|
  = form.input :age, as: :between, label: "Age between"

Predefined collection

Rather than using a select input and specifying the collection, a custom collection input type can bundle that collection and have the added benefit of including any associated input_html you care to use.

class CustomCollectionInput < SimpleForm::Inputs::CollectionSelectInput
  def input
    collection = Collection::LIST

    label_method = :to_s
    value_method = :to_s

    @builder.collection_select(
      attribute_name, collection, value_method, label_method,
      input_options, input_html_options
    )
  end

  def input_html_classes
    super.push('custom-css-class chosen-selector')
  end

end

Call in a form with

  <%= f.input :column_name, as: :custom_collection %>