1

I am trying to put together a working solution for using the date_field HTML5 date controls when the browser supports it and fall back to use the Bootstrap Datepicker if not. It seems like this is a common scenario to tackle but I haven't been able to find a solution that works for me (namely, one that doesn't involve manually adding a hidden field for every date field since I already have a bunch across a number of pages).

Using this writeup as a guide I have a partially working solution (using FireFox 49.0.2 to test):

dates.js.coffee:

datepicker = $.fn.datepicker.noConflict() # return $.fn.datepicker to previously assigned value
$.fn.bootstrapDP = datepicker  # give $().bootstrapDP the bootstrap-datepicker functionality

formatDateToPicker = (dateStr) ->
  # dateStr is what Rails emits "yyyy-mm-dd"
  parts = dateStr.split('-')
  if dateStr == ''
    return 'NoDateProvided'
  else if parts.length == 3
    return "#{parts[1]}/#{parts[2]}/#{parts[0]}"
  else
    return 'InvalidISODate'

formatDateFromPicker = (dateStr) ->
  # dateStr is what the datepicker emits "mm/dd/yyyy"
  parts = dateStr.split('/')
  if dateStr == ''
    return ''
  else if parts.length == 3
    return "#{parts[2]}-#{parts[0]}-#{parts[1]}"
  else
    return 'Invalid picker date'

set_datepicker_dates = () ->
  $("input[type='date']").each (i,e)=>
    $e = $(e)
    # create a hidden field with the name and id of the input[type=date]
    $hidden = $('<input type="hidden">')
      .attr('name', $e.attr('name'))
      .attr('id', $e.attr('id'))
      .val($e.val())
    # modify the input[type=date] field with different attributes
    $e.attr('hidden-id', $e.attr('id')) # stash the id of the hidden field
      .attr('name', "")
      .attr('id', "")
      .val(formatDateToPicker($e.val())) # transform the date
      .after($hidden) # insert the hidden field
    # attach the picker
    $e.bootstrapDP({
      #format: 'mm/dd/yyyy',
      autoclose: true,
      todayBtn: "linked",
      todayHighlight: true,
      clearBtn: true
    })
    # update the hidden field when there is an edit
    $e.on 'change', (e)=>
      $e = $(e.target)
      $v = $('#' + $e.attr('hidden-id'))
      $v.val(formatDateFromPicker($e.val()))

$(document).on 'turbolinks:load', ->
  if ($("input[type='date']").length > 0)
    unless Modernizr.inputtypes.date
      set_datepicker_dates()

show.html.erb:

<%= f.date_field :dateofbirth, placeholder: 'mm/dd/yyyy', class: 'form-control' %>

This works for normal turbolinks-based browsing/rendering, HOWEVER when I do a full browser refresh it sets the dates to "InvalidISODate". I've tried calling set_datepicker_dates() on document ready and window onload as well but neither works. Many thanks in advance for any guidance.

Update

I am now trying to get just the Bootstrap datepicker working across the board (i.e. instead of a combination of one of those and the browser's native HTML5 datepicker if available), but to no avail. My database is PostgreSQL and my date fields in the db are of type 'date', thus the default datestyle of 'ISO, MDY' is being used. I have the following code currently set up:

gemfile:

gem 'bootstrap-datepicker-rails'

application.js:

//= require bootstrap-datepicker

application.scss:

@import "bootstrap-datepicker3";

date_format.rb:

Date::DATE_FORMATS[:default] = "%m/%d/%Y"

dates.js.coffee:

$(document).on 'turbolinks:load', ->
  $('.datepicker').datepicker()

edit.html.erb:

<%= f.text_field :dateofbirth, placeholder: 'mm/dd/yyyy', class: 'form-control datepicker', autocomplete: 'off' %>

What is happening now is that I will select 02/01/2017 from the picker, it gets submitted as '2017-01-02' and thus saved to the database as Jan 1st 2017 so that when I do <%= object.dateofbirth %> in a view it is displayed as '01/02/2017'. Am I crazy? I feel crazy. Should I post a new question with my latest attempt/issue?

CChandler81
  • 347
  • 3
  • 14

1 Answers1

0

using date field in rails with bootstrap, I would suggest as follow

  • using text field with jquery-ui-rails gem detail link

here is the Gemffile

gem 'jquery-ui-rails', '~> 4.2.1'

inside application.js (put below jquery)

//= require jquery.ui.datepicker

and in your date field just use the class with datepicker, below is the sample, I also add additional code in case your want to edit the date field with f.object

<%= f.text_field :your_field, :class => 'form-control datepicker', :value=>"#{f.object.your_field.strftime("%m-%d-%Y") unless f.object.new_record? or f.object.your_field.nil?}" %>  %>

create one file in config/initializers/date_formats.rb

Date::DATE_FORMATS[:default] = "%m-%d-%Y"

don't forget to restart your rails server

widjajayd
  • 6,090
  • 4
  • 30
  • 41
  • So this would replace bootstrap-datepicker-rails or the use of the browser's native HTML date controls (if supported) with the jquery.ui.datepicker functionality? – CChandler81 Jun 27 '17 at 07:24
  • yes, just follow the link for the gem and install as requested and then for the rails field follow the one that I gave you above – widjajayd Jun 27 '17 at 07:39
  • Will this allow for displaying date as mm/dd/yyyy but still allow for database storage as yyyy-mm-dd that rails requires? – CChandler81 Jun 27 '17 at 07:44
  • I set all this up and when I submit the form the date in the parms is mm/dd/yyyy but since the db is expecting yyyy-mm-dd it returns an error saying the field can't be blank. This leads back to my original problem of not being able to display mm/dd/yyyy but submit yyyy-mm-dd that rails requires. – CChandler81 Jun 29 '17 at 07:26
  • I just added initializers setting for your date format – widjajayd Jun 29 '17 at 07:34
  • I already have that set up to control the default display of dates. It doesn't change how the application submits the date field, which is still mm/dd/yyyy with this datepicker (but needs to be yyyy-mm-dd). – CChandler81 Jun 29 '17 at 07:42
  • my understanding, if you setup the initializers that will talk to your database the format, but if you already setup the initalizers as informed above but your case still exist then I still has no other idea, sorry – widjajayd Jun 29 '17 at 07:58
  • I misspoke, you are correct that the initalizer should tell it how to submit to the database but it doesn't seem to work correctly. Maybe it's a Postgres thing. Thanks for the help. – CChandler81 Jun 29 '17 at 08:32