diff --git a/CHANGELOG.md b/CHANGELOG.md index 487f128a..00949065 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ * Add wrapper mapping per form basis [@rcillo](https://github.com/rcillo) and [@bernardoamc](https://github.com/bernardoamc) * Add `for` attribute to `label` when collections are rendered as radio or checkbox [@erichkist](https://github.com/erichkist), [@ulissesalmeida](https://github.com/ulissesalmeida) and [@fabioyamate](https://github.com/fabioyamate) * Add `include_default_input_wrapper_class` config [@luizcosta](https://github.com/luizcosta) + * Map `datetime`, `date` and `time` input types to their respective HTML5 input tags + when the `:html5` is set to `true` [@volmer](https://github.com/volmer) ### bug fix * Collection input generates `required` attribute if it has `prompt` option. [@nashby](https://github.com/nashby) diff --git a/README.md b/README.md index 7b3dbcab..ad62cb4a 100644 --- a/README.md +++ b/README.md @@ -500,9 +500,9 @@ specifying the helper method in the column `Mapping` as the `as:` option. `float` | `input[type=number]` | `float` `decimal` | `input[type=number]` | `decimal` `range` | `input[type=range]` | - - `datetime` | `input[type=datetime]` | `datetime/timestamp` - `date` | `input[type=date]` | `date` - `time` | `input[type=time]` | `time` + `datetime` | `datetime select` | `datetime/timestamp` + `date` | `date select` | `date` + `time` | `time select` | `time` `select` | `select` | `belongs_to`/`has_many`/`has_and_belongs_to_many` associations `radio_buttons` | collection of `input[type=radio]` | `belongs_to` associations `check_boxes` | collection of `input[type=checkbox]` | `has_many`/`has_and_belongs_to_many` associations diff --git a/lib/simple_form/inputs/date_time_input.rb b/lib/simple_form/inputs/date_time_input.rb index 64fd326f..0414ad2f 100644 --- a/lib/simple_form/inputs/date_time_input.rb +++ b/lib/simple_form/inputs/date_time_input.rb @@ -2,7 +2,11 @@ module SimpleForm module Inputs class DateTimeInput < Base def input - @builder.send(:"#{input_type}_select", attribute_name, input_options, input_html_options) + if use_html5_inputs? + @builder.send(:"#{input_type}_field", attribute_name, input_html_options) + else + @builder.send(:"#{input_type}_select", attribute_name, input_options, input_html_options) + end end private @@ -19,6 +23,10 @@ module SimpleForm position = ActionView::Helpers::DateTimeSelector::POSITION[position] "#{attribute_name}_#{position}i" end + + def use_html5_inputs? + input_options[:html5] + end end end end diff --git a/test/inputs/datetime_input_test.rb b/test/inputs/datetime_input_test.rb index b1a77354..d0528b1b 100644 --- a/test/inputs/datetime_input_test.rb +++ b/test/inputs/datetime_input_test.rb @@ -1,18 +1,69 @@ # encoding: UTF-8 require 'test_helper' -# Tests for all different kinds of inputs. -class DateTimeInputTest < ActionView::TestCase - # DateTime input - test 'input should generate a datetime select by default for datetime attributes' do +# Tests for datetime, date and time inputs when HTML5 compatibility is enabled in the wrapper. +class DateTimeInputWithHtml5Test < ActionView::TestCase + test 'input should generate a datetime input for datetime attributes if HTML5 compatibility is explicitly enbled' do + with_input_for @user, :created_at, :datetime, html5: true + + assert_select 'input[type="datetime"]' + end + + test 'input should generate a datetime select for datetime attributes' do with_input_for @user, :created_at, :datetime - 1.upto(5) do |i| - assert_select "form select.datetime#user_created_at_#{i}i" + + assert_select 'select.datetime' + end + + test 'input should generate a date input for date attributes if HTML5 compatibility is explicitly enbled' do + with_input_for @user, :born_at, :date, html5: true + + assert_select 'input[type="date"]' + end + + test 'input should generate a date select for date attributes' do + with_input_for @user, :born_at, :date + + assert_select 'select.date' + end + + test 'input should generate a time input for time attributes if HTML5 compatibility is explicitly enbled' do + with_input_for @user, :delivery_time, :time, html5: true + + assert_select 'input[type="time"]' + end + + test 'input should generate a time select for time attributes' do + with_input_for @user, :delivery_time, :time + + assert_select 'select.time' + end + + test 'input should generate required html attribute' do + with_input_for @user, :delivery_time, :time, required: true, html5: true + assert_select 'input.required' + assert_select 'input[required]' + end + + test 'input should have an aria-required html attribute' do + with_input_for @user, :delivery_time, :time, required: true, html5: true + assert_select 'input[aria-required=true]' + end +end + +# Tests for datetime, date and time inputs when HTML5 compatibility is enabled in the wrapper. +class DateTimeInputWithoutHtml5Test < ActionView::TestCase + test 'input should generate a datetime select by default for datetime attributes' do + swap_wrapper do + with_input_for @user, :created_at, :datetime + 1.upto(5) do |i| + assert_select "form select.datetime#user_created_at_#{i}i" + end end end test 'input should be able to pass options to datetime select' do - with_input_for @user, :created_at, :datetime, + with_input_for @user, :created_at, :datetime, html5: false, disabled: true, prompt: { year: 'ano', month: 'mês', day: 'dia' } assert_select 'select.datetime[disabled=disabled]' @@ -21,16 +72,26 @@ class DateTimeInputTest < ActionView::TestCase assert_select 'select.datetime option', 'dia' end + test 'input should generate a datetime input for datetime attributes if HTML5 compatibility is explicitly enabled' do + swap_wrapper do + with_input_for @user, :created_at, :datetime, html5: true + + assert_select 'input[type="datetime"]' + end + end + test 'input should generate a date select for date attributes' do - with_input_for @user, :born_at, :date - assert_select 'select.date#user_born_at_1i' - assert_select 'select.date#user_born_at_2i' - assert_select 'select.date#user_born_at_3i' - assert_no_select 'select.date#user_born_at_4i' + swap_wrapper do + with_input_for @user, :born_at, :date + assert_select 'select.date#user_born_at_1i' + assert_select 'select.date#user_born_at_2i' + assert_select 'select.date#user_born_at_3i' + assert_no_select 'select.date#user_born_at_4i' + end end test 'input should be able to pass options to date select' do - with_input_for @user, :born_at, :date, as: :date, + with_input_for @user, :born_at, :date, as: :date, html5: false, disabled: true, prompt: { year: 'ano', month: 'mês', day: 'dia' } assert_select 'select.date[disabled=disabled]' @@ -40,21 +101,31 @@ class DateTimeInputTest < ActionView::TestCase end test 'input should be able to pass :default to date select' do - with_input_for @user, :born_at, :date, default: Date.today + with_input_for @user, :born_at, :date, default: Date.today, html5: false assert_select "select.date option[value=#{Date.today.year}][selected=selected]" end + test 'input should generate a date input for date attributes if HTML5 compatibility is explicitly enabled' do + swap_wrapper do + with_input_for @user, :born_at, :date, html5: true + + assert_select 'input[type="date"]' + end + end + test 'input should generate a time select for time attributes' do - with_input_for @user, :delivery_time, :time - assert_select 'input[type=hidden]#user_delivery_time_1i' - assert_select 'input[type=hidden]#user_delivery_time_2i' - assert_select 'input[type=hidden]#user_delivery_time_3i' - assert_select 'select.time#user_delivery_time_4i' - assert_select 'select.time#user_delivery_time_5i' + swap_wrapper do + with_input_for @user, :delivery_time, :time + assert_select 'input[type=hidden]#user_delivery_time_1i' + assert_select 'input[type=hidden]#user_delivery_time_2i' + assert_select 'input[type=hidden]#user_delivery_time_3i' + assert_select 'select.time#user_delivery_time_4i' + assert_select 'select.time#user_delivery_time_5i' + end end test 'input should be able to pass options to time select' do - with_input_for @user, :delivery_time, :time, required: true, + with_input_for @user, :delivery_time, :time, required: true, html5: false, disabled: true, prompt: { hour: 'hora', minute: 'minuto' } assert_select 'select.time[disabled=disabled]' @@ -62,44 +133,40 @@ class DateTimeInputTest < ActionView::TestCase assert_select 'select.time option', 'minuto' end + test 'input should generate a time input for time attributes if HTML5 compatibility is explicitly enabled' do + swap_wrapper do + with_input_for @user, :delivery_time, :time, html5: true + + assert_select 'input[type="time"]' + end + end + test 'label should use i18n to get target for date input type' do store_translations(:en, date: { order: ['month', 'day', 'year'] }) do - with_input_for :project, :created_at, :date + with_input_for :project, :created_at, :date, html5: false assert_select 'label[for=project_created_at_2i]' end end test 'label should use i18n to get target for datetime input type' do store_translations(:en, date: { order: ['month', 'day', 'year'] }) do - with_input_for :project, :created_at, :datetime + with_input_for :project, :created_at, :datetime, html5: false assert_select 'label[for=project_created_at_2i]' end end test 'label should use order to get target when date input type' do - with_input_for :project, :created_at, :date, order: ['month', 'year', 'day'] + with_input_for :project, :created_at, :date, order: ['month', 'year', 'day'], html5: false assert_select 'label[for=project_created_at_2i]' end test 'label should use order to get target when datetime input type' do - with_input_for :project, :created_at, :datetime, order: ['month', 'year', 'day'] + with_input_for :project, :created_at, :datetime, order: ['month', 'year', 'day'], html5: false assert_select 'label[for=project_created_at_2i]' end test 'label should point to first option when time input type' do - with_input_for :project, :created_at, :time + with_input_for :project, :created_at, :time, html5: false assert_select 'label[for=project_created_at_4i]' end - - test 'date time input should generate required html attribute' do - with_input_for @user, :delivery_time, :time, required: true - assert_select 'select.required' - assert_select 'select[required]' - end - - test 'date time input has an aria-required html attribute' do - with_input_for @user, :delivery_time, :time, required: true - assert_select 'select.required' - assert_select 'select[aria-required=true]' - end end