Rails 5 - Using bootstrap datepicker unless browse

2019-05-30 02:51发布

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?

1条回答
疯言疯语
2楼-- · 2019-05-30 03:27

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

查看更多
登录 后发表回答