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
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();
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
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:
- add
DatepickerInput
to its list of inputs - make sure the
simple_form_bootstrap3.rb
(or similar) initializer loads aftersimple_form_datepicker.rb
, so that theDatepickerInput
class is available. Do that by e.g. renaming the datepicker initializer tosimple_form_0_datepicker.rb
.
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.
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" %>
精彩评论