1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Add include_seconds option for time_field

Per https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/time#time_value_format, if you format your time without seconds, the UI browsers render may differ. This adds support for this to Rails so that users don't need to call `strftime` on the value being passed into the form.
This commit is contained in:
Alex Ghiculescu 2021-03-22 12:38:15 -05:00
parent ab13f9549d
commit 8e9615c1ca
5 changed files with 44 additions and 5 deletions

View file

@ -1,3 +1,17 @@
* Add `include_seconds` option for `time_field`
<%= form.time_field :foo, include_seconds: false %>
# => <input value="16:22" type="time" />
Default includes seconds:
<%= form.time_field :foo %>
# => <input value="16:22:01.440" type="time" />
This allows you to take advantage of [different rendering options](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/time#time_value_format) in some browsers.
*Alex Ghiculescu*
* The `translate` helper now passes `default` values that aren't
translation keys through `I18n.translate` for interpolation.
@ -49,12 +63,12 @@
the first argument or as a block.
<%= button_to "Delete", post_path(@post), method: :delete %>
<%# => <form action="/posts/1"><input type="hidden" name="_method" value="delete"><button type="submit">Delete</button></form>
# => <form action="/posts/1"><input type="hidden" name="_method" value="delete"><button type="submit">Delete</button></form>
<%= button_to post_path(@post), method: :delete do %>
Delete
<% end %>
<%# => <form action="/posts/1"><input type="hidden" name="_method" value="delete"><button type="submit">Delete</button></form>
# => <form action="/posts/1"><input type="hidden" name="_method" value="delete"><button type="submit">Delete</button></form>
*Sean Doyle*, *Dusan Orlovic*

View file

@ -1402,8 +1402,9 @@ module ActionView
# Returns a text_field of type "time".
#
# The default value is generated by trying to call +strftime+ with "%T.%L"
# on the object's value. It is still possible to override that
# by passing the "value" option.
# on the object's value. If you pass "include_seconds: false", it will be
# formatted by trying to call +strftime+ with "%H:%M" on the object's value.
# It is also possible to override this by passing the "value" option.
#
# === Options
# * Accepts same options as time_field_tag
@ -1424,6 +1425,12 @@ module ActionView
# time_field("task", "started_at", min: "01:00:00")
# # => <input id="task_started_at" name="task[started_at]" type="time" min="01:00:00.000" />
#
# By default, provided times will be formatted including seconds. You can render just the hour
# and minute by passing `include_seconds: false`. Some browsers will render a simpler UI
# if you exclude seconds in the timestamp format.
#
# time_field("task", "started_at", value: Time.now, include_seconds: false)
# # => <input id="task_started_at" name="task[started_at]" type="time" value="01:00" />
def time_field(object_name, method, options = {})
Tags::TimeField.new(object_name, method, self, options).render
end

View file

@ -713,6 +713,7 @@ module ActionView
# * <tt>:min</tt> - The minimum acceptable value.
# * <tt>:max</tt> - The maximum acceptable value.
# * <tt>:step</tt> - The acceptable value granularity.
# * <tt>:include_seconds</tt> - Include seconds and ms in the output timestamp format (true by default).
# * Otherwise accepts the same options as text_field_tag.
def time_field_tag(name, value = nil, options = {})
text_field_tag(name, value, options.merge(type: :time))

View file

@ -4,9 +4,18 @@ module ActionView
module Helpers
module Tags # :nodoc:
class TimeField < DatetimeField # :nodoc:
def initialize(object_name, method_name, template_object, options = {})
@include_seconds = options.delete(:include_seconds) { true }
super
end
private
def format_date(value)
if @include_seconds
value&.strftime("%T.%L")
else
value&.strftime("%H:%M")
end
end
end
end

View file

@ -1156,6 +1156,14 @@ class FormHelperTest < ActionView::TestCase
assert_dom_equal(expected, time_field("post", "written_on", min: min_value, max: max_value))
end
def test_time_field_without_seconds
expected = %{<input id="post_written_on" name="post[written_on]" type="time" value="01:02" max="10:25" min="20:45" />}
@post.written_on = DateTime.new(2004, 6, 15, 1, 2, 3)
min_value = DateTime.new(2000, 6, 15, 20, 45, 30)
max_value = DateTime.new(2010, 8, 15, 10, 25, 00)
assert_dom_equal(expected, time_field("post", "written_on", include_seconds: false, min: min_value, max: max_value))
end
def test_datetime_field
expected = %{<input id="post_written_on" name="post[written_on]" type="datetime-local" value="2004-06-15T00:00:00" />}
assert_dom_equal(expected, datetime_field("post", "written_on"))