Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do i write a cleaner date picker input for SimpleForm

I love the simple_form gem for rails but i dont like this line of code:

<%= f.input :deadline, :as => :string, :input_html => { :class => 'date_picker' } %>

I would like to write:

<%= f.input :deadline, :as => :date_picker %>

or even over write the :date / :datetime matchers completely.

But i dont really want to write a whole custom_simple_form

I think it must be possible...

Please help thanks

like image 273
nodrog Avatar asked Feb 15 '11 18:02

nodrog


3 Answers

The answers here seem a bit out of date if you are using simple_form 2.0.

I've been fighting with this for a while and was able to concoct this; it uses inheritance (notice that it is a subclass of StringInput, not Base), supports i18n and adds the datepicker css class in a more clean way, IMHO.

# app/inputs/date_picker_input.rb

class DatePickerInput < SimpleForm::Inputs::StringInput 
  def input                    
    value = input_html_options[:value]
    value ||= object.send(attribute_name) if object.respond_to? attribute_name
    input_html_options[:value] ||= I18n.localize(value) if value.present?
    input_html_classes << "datepicker"

    super # leave StringInput do the real rendering
  end
end

The usage is like above:

<%= f.input :deadline, :as => :date_picker %>

And the javascript remains the same:

$("input.date_picker").datepicker();
like image 120
kikito Avatar answered Oct 24 '22 03:10

kikito


You have to define a new DatePickerInput class.

module SimpleForm
  module Inputs
    class DatePickerInput < Base
      def input
        @builder.text_field(attribute_name,input_html_options)
      end    
    end
  end
end

And you can now write

<%= f.input :deadline, :as => :date_picker %>

Off course you also need

 $("input.date_picker").datepicker();

in application.js

This is very useful to localize dates. Look at this:

module SimpleForm
  module Inputs
    class DatePickerInput < Base
      def input
        @builder.text_field(attribute_name, input_html_options.merge(datepicker_options(object.send(attribute_name))))
      end

      def datepicker_options(value = nil)
        datepicker_options = {:value => value.nil?? nil : I18n.localize(value)}
      end

    end
  end
end

You have now a localized date in the text field!

Update: a cleaner way to do the same

module SimpleForm
  module Inputs
    class DatePickerInput < SimpleForm::Inputs::StringInput
      def input_html_options
        value = object.send(attribute_name)
        options = {
          value: value.nil?? nil : I18n.localize(value),
          data: { behaviour: 'datepicker' }  # for example
        }
        # add all html option you need...
        super.merge options
      end
    end
  end
end

Inherit from SimpleForm::Inputs::StringInput (as @kikito said) and add some html options. If you need also a specific class you can add something like

def input_html_classes
  super.push('date_picker')
end
like image 43
vicvega Avatar answered Oct 24 '22 03:10

vicvega


Based on @kikito's answer, I did this to get a native datepicker (i.e. no special JS classes).

config/initializers/simple_form_datepicker.rb

class SimpleForm::Inputs::DatepickerInput < SimpleForm::Inputs::StringInput 
  def input                    
    input_html_options[:type] = "date"
    super
  end
end

Then used it like:

f.input :paid_on, as: :datepicker

Note that if you also have a simple_form_bootstrap3.rb initializer or similar, like we did, you should:

  1. add DatepickerInput to its list of inputs
  2. make sure the simple_form_bootstrap3.rb (or similar) initializer loads after simple_form_datepicker.rb, so that the DatepickerInput class is available. Do that by e.g. renaming the datepicker initializer to simple_form_0_datepicker.rb.
like image 8
Henrik N Avatar answered Oct 24 '22 02:10

Henrik N