Separate date and time form fields in Rails

后端 未结 5 656
轮回少年
轮回少年 2020-12-23 16:43

I have an ActiveRecord model Eventwith a datetime column starts_at. I would like to present a form, where date and time for starts_at

相关标签:
5条回答
  • 2020-12-23 17:03

    Elegant solution may provide date_time_attribute gem:

    class MyModel < ActiveRecord::Base
      include DateTimeAttribute
    
      date_time_attribute :starts_at
    end
    

    It will allow you to set starts_at_date and starts_at_time separately:

    form_for @event do |f|
      f.text_field :starts_at_date
      f.text_field :starts_at_time
      f.submit
    end
    
    # this will work too:
    form_for @event do |f|
      f.date_select :starts_at_date
      f.time_select :starts_at_time, :ignore_date => true
      f.text_field  :starts_at_time_zone
      f.submit
    end
    
    # or
    form_for @event do |f|
      f.date_select :starts_at_date
      f.text_field  :starts_at_time
      f.submit
    end
    

    It will also allow you to play with time zones, use Chronic etc.

    0 讨论(0)
  • 2020-12-23 17:10

    Is this because of a design issue? It is really much easier if you just save starts_at as a datetime data type and use something like:

    http://puna.net.nz/timepicker.htm#

    It simply runs on top of whatever date fields you have for your model.

    0 讨论(0)
  • 2020-12-23 17:15

    Do you have to have a text_field in the view?

    As far as I can tell, you can have a date_time field and then just use two different input fields to set the different parts of the field.

    form_for @event do |f|
      f.date_select :starts_at
      f.time_select :starts_at, :ignore_date => true
      f.submit
    end
    

    Since the rails date and time select helpers set five different parameters (starts_at(1i) for the year part, 2i for the month part, and so on), that means that the date_select only sets them for the date part, while if you pass :ignore_date => true to the time_select, it will only set the hour and minute part.

    If you must have a text_field I'm not sure how to do it, but it might be possible to do using some jQuery magic before setting the datetime parameters before sending the form.

    0 讨论(0)
  • 2020-12-23 17:21

    Was looking at this today for a Rails project, and came across this gem:

    https://github.com/shekibobo/time_splitter

    Setting DateTimes can be a difficult or ugly thing, especially through a web form. Finding a good DatePicker or TimePicker is easy, but getting them to work on both can be difficult. TimeSplitter automatically generates accessors for date, time, hour, and min on your datetime or time attributes, making it trivial to use different form inputs to set different parts of a datetime field.

    Looks like it would do the job for you

    0 讨论(0)
  • 2020-12-23 17:24

    Using a date_select and time_select is a good way to go.

    However, I wanted a text_field for the date (so I can use a JavaScript date picker).

    Using strong_parameters or Rails 4+:

    models/event.rb

    # Add a virtual attribute
    attr_accessor :start_at_date
    

    views/events/_form.html.haml

    - # A text field for the date, and time_select for time
    = f.label :start_at
    = f.text_field :start_at_date, value: (f.object.start_at.present? ? f.object.start_at.to_date : nil)
    = f.time_select :start_at, :ignore_date => true
    

    controllers/events_controller.rb

    # If using a date_select, time_select, datetime_select
    # Rails expects multiparameter attributes
    # Convert the date to the muiltiparameter parts
    def event_params
      if !!params[:event] && (params[:event]["start_at(4i)"].present? || params[:event]["start_at(5i)"].present?)
    
        if params[:event][:start_at_date].present?
          start_at_date = params[:event][:start_at_date]
        else
          start_at_date = Date.today
        end
        year  = start_at_date.match(/^(\d{4})[\-\/]/)[1]
        month = start_at_date.match(/[\-\/](\d{2})[\-\/]/)[1]
        day   = start_at_date.match(/[\-\/](\d{2})$/)[1]
        params[:event]["start_at(1i)"] = year
        params[:event]["start_at(2i)"] = month
        params[:event]["start_at(3i)"] = day
      end
      ...
    
    0 讨论(0)
提交回复
热议问题