I love the simple_form
gem for rails but i dont like this line of code:
<%= f.input :deadline, :as => :string, :input_html => { :class
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();
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:
DatepickerInput
to its list of inputssimple_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
.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
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" %>