How do i write a cleaner date picker input for SimpleForm

后端 未结 5 1742
萌比男神i
萌比男神i 2020-12-04 07:23

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

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


        
相关标签:
5条回答
  • 2020-12-04 08:03

    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();
    
    0 讨论(0)
  • 2020-12-04 08:06

    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.
    0 讨论(0)
  • 2020-12-04 08:28

    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
    
    0 讨论(0)
  • 2020-12-04 08:28

    An other option could also be to overwrite the default DateTimeInput helper, here's an example to be placed in app/inputs/date_time_input.rb

    class DateTimeInput < SimpleForm::Inputs::DateTimeInput
      def input
        add_autocomplete!
        @builder.text_field(attribute_name, input_html_options.merge(datetime_options(object.send(attribute_name))))
      end
    
      def label_target
        attribute_name
      end
    
      private
    
        def datetime_options(value = nil)
          return {} if value.nil?
    
          current_locale = I18n.locale
          I18n.locale = :en
    
          result = []
          result.push(I18n.localize(value, { :format => "%a %d %b %Y" })) if input_type =~ /date/
          if input_type =~ /time/
            hours_format = options[:"24hours"] ? "%H:%M" : "%I:%M %p"
            result.push(I18n.localize(value, { :format => hours_format }))
          end
    
          I18n.locale = current_locale
    
          { :value => result.join(', ').html_safe }
        end
    
        def has_required?
          options[:required]
        end
    
        def add_autocomplete!
          input_html_options[:autocomplete] ||= 'off'
        end
    end
    

    Please notice than while using this method makes it a drop feature for your forms, it might also break with future versions of simple_form.

    Notice about localized dates: As far as I know Ruby interprets dates following only a few formats, you might want to be careful before localizing them and make sure Ruby can handle them. An attempt to better localization support on the Ruby Date parsing as been started at https://github.com/ZenCocoon/I18n-date-parser, yet, this is not working.

    0 讨论(0)
  • 2020-12-04 08:29

    In new formtastic previews answers doesn't work. See http://justinfrench.com/notebook/formtastic-2-preview-custom-inputs Here is a simple working example (save to app/inputs/date_picker_input.rb):

    class DatePickerInput < Formtastic::Inputs::StringInput
      def input_html_options
        {
          :class => 'date_picker',
        }.merge(super).merge({
          :size => '11'
        })
      end
    end
    

    Create a file app/assets/javascripts/date_picker.js with content:

    $(function() {
      $("input#.date_picker").datepicker();
    });
    

    You also need to load jquery-ui. To do so, insert to app/assets/javascripts/application.js line:

    //= require jquery-ui
    

    or simply use CDN eg:

    <%= javascript_include_tag "http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js" %>
    <%= javascript_include_tag "http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.1/jquery-ui.min.js" %>
    

    Stylesheets for jquery-ui coul be inclded http://babinho.net/2011/10/rails-3-1-jquery-ui/ or from CDN:

    <%= stylesheet_link_tag    "application", "http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.8/themes/ui-lightness/jquery-ui.css" %>
    
    0 讨论(0)
提交回复
热议问题