如何为SimpleForm编写更清晰的日期选择器输入

时间:2011-02-15 18:24:50

标签: ruby-on-rails ruby-on-rails-3 forms

我喜欢用于rails的simple_form gem,但我不喜欢这行代码:

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

我想写:

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

甚至完全写完:date / :datetime匹配器。

但我真的不想写一整个custom_simple_form

我认为一定有可能......

请帮助谢谢

5 个答案:

答案 0 :(得分:42)

如果你使用的是simple_form 2.0,这里的答案似乎有些过时了。

我已经和它斗争了一段时间,并且能够制造这个;它使用继承(注意它是StringInput的子类,而不是Base),支持i18n并以更干净的方式添加datepicker css类,恕我直言。

# 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

用法如上:

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

javascript保持不变:

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

答案 1 :(得分:37)

您必须定义一个新的DatePickerInput类。

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

你现在可以写

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

当然你还需要

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

中的

这对本地化日期非常有用。看看这个:

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

您现在在文本字段中有一个本地化日期!

更新:更简洁的方法

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

继承自SimpleForm::Inputs::StringInput(如@kikito所说)并添加一些html选项。 如果您还需要特定课程,可以添加类似

的内容
def input_html_classes
  super.push('date_picker')
end

答案 2 :(得分:6)

根据@ kikito的回答,我这样做是为了获得一个原生的日期选择器(即没有特殊的JS类)。

<强>配置/初始化/ simple_form_datepicker.rb

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

然后用它:

f.input :paid_on, as: :datepicker

请注意,如果您还有 simple_form_bootstrap3.rb 初始化程序或类似程序,就像我们一样,您应该:

  1. DatepickerInput添加到其输入列表
  2. 确保simple_form_bootstrap3.rb(或类似的)初始化程序在 simple_form_datepicker.rb之后加载,以便DatepickerInput类可用。通过例如这样做将datepicker初始化程序重命名为simple_form_0_datepicker.rb

答案 3 :(得分:0)

另一个选项也可能是覆盖默认的DateTimeInput助手,这是一个放在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

请注意,使用此方法时使其成为表单的删除功能,它可能会破坏simple_form的未来版本。

关于本地化日期的注意事项:据我所知,Ruby仅按照几种格式解释日期,您可能需要在本地化之前小心并确保Ruby可以处理它们。 在https://github.com/ZenCocoon/I18n-date-parser开始尝试更好地对Ruby Date解析进行本地化支持,但是,这不起作用。

答案 4 :(得分:-1)

在新的formtastic预览中,答案不起作用。见http://justinfrench.com/notebook/formtastic-2-preview-custom-inputs 这是一个简单的工作示例(保存到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

使用内容:

创建文件app / assets / javascripts / date_picker.js
$(function() {
  $("input#.date_picker").datepicker();
});

您还需要加载jquery-ui。为此,请插入app / assets / javascripts / application.js行:

//= require jquery-ui

或仅使用CDN,例如:

<%= 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" %>

jquery-ui coul的样式表可以覆盖http://babinho.net/2011/10/rails-3-1-jquery-ui/或 来自CDN:

<%= stylesheet_link_tag    "application", "http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.8/themes/ui-lightness/jquery-ui.css" %>