public

Simple Form custom input for "Datepicker for Twitter Bootstrap" running under Ruby on Rails with Ransack search

  • Download Gist
app-assets-javascript-datepicker.js.coffee
CoffeeScript
1 2 3 4 5 6 7 8 9 10 11
# install and make run basic bootstrap date-picker functionality described here http://www.eyecon.ro/bootstrap-datepicker/
 
# app/assets/javascript/datepicker.js.coffee
$(document).on 'pageChanged', ->
 
# datepicker for simple_form & Ransack
$(".custom_datepicker_selector").datepicker().on 'changeDate', (en) ->
correct_format = en.date.getFullYear() + '-' + ('0' + (en.date.getMonth() + 1)).slice(-2) + '-' + ('0' + en.date.getDate()).slice(-2) # date format yyyy-mm-dd
$(this).parent().find("input[type=hidden]").val(correct_format)
 
#Note if you refactor a bit it will work with jOuery date-picker
app-controllers-posts_controller.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14
# gem Ransack is used for search https://github.com/ernie/ransack/
 
#app/controllers/posts_controller.rb
class PostsController < ApplicationController
def index
#will display advanced search results
@search = Post.search(params[:q])
@posts = @search.result(:district => true).page(params[:page])
end
 
def advanced_search
@search = Post.search(params[:q])
end
end
app-inputs-custom_datepicker_input.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
# more on https://github.com/plataformatec/simple_form/ ...look for "Custom inputs"
 
#app/inputs/custom_datepicker_input.rb
class CustomDatepickerInput < SimpleForm::Inputs::Base
def input
text_field_options = input_html_options.dup
hidden_field_options = input_html_options.dup
hidden_field_options[:class] = input_html_options[:class].dup # so they won't work with same array object
 
text_field_options[:class] << 'custom_datepicker_selector'
text_field_options['data-date-format'] = I18n.t('date.datepicker')
 
hidden_field_options[:id] = "#{attribute_name}_hidden"
 
return_string =
"#{@builder.text_field(attribute_name, text_field_options)}\n" +
"#{@builder.hidden_field(attribute_name, hidden_field_options)}\n"
return return_string.html_safe
end
end
app-views-posts-advanced_search.html.haml
Haml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
-#app/views/posts/advanced_search.html.haml
.advanced_search
= simple_form_for @search,:method=>'get', :url=>posts_path do |f|
.form-inputs
= f.input :name_cont
= f.input :email_cont
 
.row-fluid
.span5
.form-inputs
= f.input :created_at_gt, :as =>:custom_datepicker, :label => 'Created from'
.span5
.form-inputs
= f.input :created_at_lt, :as =>:custom_datepicker, :label => 'Created till'
.form-actions
= f.submit 'Search', class: 'btn-primary'
 
 
 
-# Note: divs row-fluid, span5, form-inputs, form-actions have nothing to do with functionality of javascript, they are just Simple Form & Bootstrap wrappers
config-locales-en.yml
YAML
1 2 3 4
#config/locales/en.yml
en:
date:
datepicker: "mm/dd/yyyy"
spec-helpers-simple_form_inputs_helper_spec.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
# I was trying to put my spec to spec/imputs/... but unfortunately, I had some RSpec troubles (see http://stackoverflow.com/questions/11341136/how-to-tell-rails-rspec-that-spec-is-type-helper)
 
 
#spec/helpers/simple_form_inputs_helper_spec.rb
require 'spec_helper'
describe 'CustomDatepickerInput' do
describe 'input' do
let(:date_format){'mm:dd:yyyy'}
before :each do
I18n.stub(:t){date_format}
@html = helper.simple_form_for Post.search(),:method=>'get', :url=>helper.posts_path do |f|
f.input :created_at, :as =>:custom_datepicker
end
end
 
it 'simple form should generate just one control-group for this scenario' do
# no need to test <form>, it's all ready tested with simple form
@html.should have_css('form div.control-group', :count=>1 )
end
 
it 'form should have label link pointing to text input' do
@html.should have_selector('form label[for=q_created_at]' )
end
 
describe 'form div.controls' do
it 'should have only 2 input fields' do
# watch out: simple form is rendering one extra hidden field outside div.controls
@html.should have_css('form div.controls input', :count=>2 )
end
 
describe 'text field input ' do
it 'should be present once' do
@html.should have_selector('div.controls input[type=text]', :count =>1 )
end
 
it 'should have id from default simple form generator' do
@html.should have_selector('div.controls input#q_created_at[type=text]' )
end
 
it 'should have name from default simple form generator' do
@html.should have_selector("div.controls input[type=text][name='q[created_at]']" )
end
 
it 'should have class="custom_datepicker_selector"' do
@html.should have_selector("div.controls input.custom_datepicker_selector[type=text]" )
end
 
it 'should have date-format from locals' do
@html.should have_selector("div.controls input[type=text][data-date-format='#{date_format}']")
end
end
 
describe 'hidden field input ' do
it 'should be present once' do
@html.should have_selector('div.controls input[type=hidden]', :count =>1 )
end
 
it 'should have id = action_name + _hidden suffix' do
@html.should have_selector('div.controls input#created_at_hidden[type=hidden]' )
end
 
it 'should have name from default simple form generator' do
@html.should have_selector("div.controls input[type=text][name='q[created_at]']" )
end
 
it 'should not have custom_datepicker_selector class' do
@html.should_not have_selector('div.controls input.custom_datepicker_selector[type=hidden]' )
end
 
it 'should not have date-format' do
@html.should_not have_selector("div.controls input[type=hidden][data-date-format]" )
end
end
end
end
end

Datepicker will show US format in text input field (e.g. 07/03/2012) but hidden input field will be set with database format date (e.g. 2012-07-03) so Ransack will pickup params as

   "q"=>{"created_at_gt"=>"2012-07-03"}

related posts
http://stackoverflow.com/questions/11341136/how-to-tell-rails-rspec-that-spec-is-type-helper
http://stackoverflow.com/questions/11328844/how-to-tell-ransack-gem-to-recognize-datepicker-us-format

just one more thing,.... when user disable JavaScript and he manually type date to text form, hidden field will still overwrite this input. So if you want bulletproof solution, rewrite this that the hidden field should be dynamically added by JS ( or something similar)

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.