Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save equivalent/3053409 to your computer and use it in GitHub Desktop.
Save equivalent/3053409 to your computer and use it in GitHub Desktop.
Simple Form custom input for "Datepicker for Twitter Bootstrap" running under Ruby on Rails with Ransack search
# 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
# 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
# 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
.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
en:
date:
datepicker: "mm/dd/yyyy"
# 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
@equivalent
Copy link
Author

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)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment