diff --git a/dist/client-side-validations.esm.js b/dist/client-side-validations.esm.js index 7cd7a60a5..0b42a8c5a 100644 --- a/dist/client-side-validations.esm.js +++ b/dist/client-side-validations.esm.js @@ -626,6 +626,8 @@ var cleanNestedElementName = function cleanNestedElementName(elementName, nested var cleanElementName = function cleanElementName(elementName, validators) { elementName = elementName.replace(/\[(\w+_attributes)\]\[[\da-z_]+\](?=\[(?:\w+_attributes)\])/g, '[$1][]'); + elementName = elementName.replace(/\(\di\)/g, ''); // date/time_select (1/2/3/4/5i) fields + var nestedMatches = elementName.match(/\[(\w+_attributes)\].*\[(\w+)\]$/); if (nestedMatches) { diff --git a/dist/client-side-validations.js b/dist/client-side-validations.js index 94f5658dd..f94a2fcea 100644 --- a/dist/client-side-validations.js +++ b/dist/client-side-validations.js @@ -632,6 +632,8 @@ var cleanElementName = function cleanElementName(elementName, validators) { elementName = elementName.replace(/\[(\w+_attributes)\]\[[\da-z_]+\](?=\[(?:\w+_attributes)\])/g, '[$1][]'); + elementName = elementName.replace(/\(\di\)/g, ''); // date/time_select (1/2/3/4/5i) fields + var nestedMatches = elementName.match(/\[(\w+_attributes)\].*\[(\w+)\]$/); if (nestedMatches) { diff --git a/lib/client_side_validations/action_view/form_builder.rb b/lib/client_side_validations/action_view/form_builder.rb index 5baa9e700..121ea47ed 100644 --- a/lib/client_side_validations/action_view/form_builder.rb +++ b/lib/client_side_validations/action_view/form_builder.rb @@ -62,6 +62,15 @@ def collection_select(method, collection, value_method, text_method, options = { super(method, collection, value_method, text_method, options, html_options) end + %i[date_select datetime_select time_select].each do |method_name| + define_method method_name do |method, options = {}, html_options = {}| + build_validation_options(method, options) + html_options.delete(:validate) + + super(method, options, html_options) + end + end + def fields_for(record_name, record_object = nil, fields_options = {}, &block) if record_object.is_a?(Hash) && record_object.extractable_options? fields_options = record_object diff --git a/src/main.js b/src/main.js index fe6ae0410..f2d45b98a 100644 --- a/src/main.js +++ b/src/main.js @@ -82,6 +82,7 @@ const cleanNestedElementName = (elementName, nestedMatches, validators) => { const cleanElementName = (elementName, validators) => { elementName = elementName.replace(/\[(\w+_attributes)\]\[[\da-z_]+\](?=\[(?:\w+_attributes)\])/g, '[$1][]') + elementName = elementName.replace(/\(\di\)/g, '') // date/time_select (1/2/3/4/5i) fields const nestedMatches = elementName.match(/\[(\w+_attributes)\].*\[(\w+)\]$/) diff --git a/test/action_view/cases/test_form_for_helpers.rb b/test/action_view/cases/test_form_for_helpers.rb index c1460ba61..cfb109548 100644 --- a/test/action_view/cases/test_form_for_helpers.rb +++ b/test/action_view/cases/test_form_for_helpers.rb @@ -432,6 +432,42 @@ def test_time_zone_select_with_validate_options assert_dom_equal expected, output_buffer end + def test_date_select + form_for(@post, validate: true) do |f| + concat f.date_select(:cost) + end + + validators = { 'post[cost]' => { presence: [{ message: "can't be blank" }] } } + expected = whole_form_for('/posts', 'new_post', 'new_post', validators: validators) do + date_select :post, :cost + end + assert_dom_equal expected, output_buffer + end + + def test_datetime_select + form_for(@post, validate: true) do |f| + concat f.datetime_select(:cost) + end + + validators = { 'post[cost]' => { presence: [{ message: "can't be blank" }] } } + expected = whole_form_for('/posts', 'new_post', 'new_post', validators: validators) do + datetime_select :post, :cost + end + assert_dom_equal expected, output_buffer + end + + def test_time_select + form_for(@post, validate: true) do |f| + concat f.time_select(:cost) + end + + validators = { 'post[cost]' => { presence: [{ message: "can't be blank" }] } } + expected = whole_form_for('/posts', 'new_post', 'new_post', validators: validators) do + time_select :post, :cost + end + assert_dom_equal expected, output_buffer + end + def test_as_form_option_with_new_record_rails form_for(@post, as: :article, validate: true) do concat content_tag(:span, 'Dummy Content') diff --git a/test/action_view/cases/test_form_with_helpers.rb b/test/action_view/cases/test_form_with_helpers.rb index 792f3accb..8377d417b 100644 --- a/test/action_view/cases/test_form_with_helpers.rb +++ b/test/action_view/cases/test_form_with_helpers.rb @@ -462,6 +462,43 @@ def test_form_with_time_zone_select_with_validate_options assert_dom_equal expected, output_buffer end + def test_form_with_date_select + form_with(model: @post, validate: true) do |f| + concat f.date_select(:cost) + end + + validators = { 'post[cost]' => { presence: [{ message: "can't be blank" }] } } + expected = whole_form_with('/posts', validators: validators) do + date_select :post, :cost + end + assert_dom_equal expected, output_buffer + end + + def test_form_with_datetime_select + form_with(model: @post, validate: true) do |f| + concat f.datetime_select(:cost) + end + + validators = { 'post[cost]' => { presence: [{ message: "can't be blank" }] } } + expected = whole_form_with('/posts', validators: validators) do + datetime_select :post, :cost + end + assert_dom_equal expected, output_buffer + end + + def test_form_with_time_select + form_with(model: @post, validate: true) do |f| + concat f.time_select(:cost) + end + + validators = { 'post[cost]' => { presence: [{ message: "can't be blank" }] } } + expected = whole_form_with('/posts', validators: validators) do + time_select :post, :cost + end + + assert_dom_equal expected, output_buffer + end + def test_form_with_as_form_option_with_new_record_rails form_with(model: @post, as: :article, validate: true) do concat content_tag(:span, 'Dummy Content') diff --git a/test/action_view/cases/test_legacy_form_for_helpers.rb b/test/action_view/cases/test_legacy_form_for_helpers.rb index 1e5c0b0db..0a04ae18d 100644 --- a/test/action_view/cases/test_legacy_form_for_helpers.rb +++ b/test/action_view/cases/test_legacy_form_for_helpers.rb @@ -41,6 +41,39 @@ def test_file_field assert_dom_equal expected, output_buffer end + def test_date_select + form_for(@post) do |f| + concat f.date_select(:cost) + end + + expected = whole_form_for('/posts', 'new_post', 'new_post') do + date_select :post, :cost + end + assert_dom_equal expected, output_buffer + end + + def test_datetime_select + form_for(@post) do |f| + concat f.datetime_select(:cost) + end + + expected = whole_form_for('/posts', 'new_post', 'new_post') do + datetime_select :post, :cost + end + assert_dom_equal expected, output_buffer + end + + def test_time_select + form_for(@post) do |f| + concat f.time_select(:cost) + end + + expected = whole_form_for('/posts', 'new_post', 'new_post') do + time_select :post, :cost + end + assert_dom_equal expected, output_buffer + end + def test_check_box form_for(@post) do |f| concat f.check_box(:cost) diff --git a/test/action_view/cases/test_legacy_form_with_helpers.rb b/test/action_view/cases/test_legacy_form_with_helpers.rb index 7cc3b08b3..c2964b3d5 100644 --- a/test/action_view/cases/test_legacy_form_with_helpers.rb +++ b/test/action_view/cases/test_legacy_form_with_helpers.rb @@ -46,6 +46,40 @@ def test_form_with_file_field assert_dom_equal expected, output_buffer end + def test_form_with_date_select + form_with(model: @post) do |f| + concat f.date_select(:cost) + end + + expected = whole_form_with('/posts') do + date_select :post, :cost + end + assert_dom_equal expected, output_buffer + end + + def test_form_with_datetime_select + form_with(model: @post) do |f| + concat f.datetime_select(:cost) + end + + expected = whole_form_with('/posts') do + datetime_select :post, :cost + end + assert_dom_equal expected, output_buffer + end + + def test_form_with_time_select + form_with(model: @post) do |f| + concat f.time_select(:cost) + end + + expected = whole_form_with('/posts') do + time_select :post, :cost + end + + assert_dom_equal expected, output_buffer + end + def test_form_with_check_box form_with(model: @post) do |f| concat f.check_box(:cost) diff --git a/test/javascript/public/test/validateElement.js b/test/javascript/public/test/validateElement.js index 431e643f9..9809d9827 100644 --- a/test/javascript/public/test/validateElement.js +++ b/test/javascript/public/test/validateElement.js @@ -18,7 +18,10 @@ QUnit.module('Validate Element', { 'user[phone_numbers_attributes][deeply][nested][][attribute]': { presence: [{ message: 'must be present' }] }, 'user[phone_numbers_attributes][][labels_attributes][][label]': { presence: [{ message: 'must be present' }] }, 'user[a_attributes][][b_attributes][][c_attributes][][d_attributes][][e]': { presence: [{ message: 'must be present' }] }, - customized_field: { length: [{ messages: { minimum: 'is too short (minimum is 4 characters)' }, minimum: 4 }] } + customized_field: { length: [{ messages: { minimum: 'is too short (minimum is 4 characters)' }, minimum: 4 }] }, + 'user[date_of_sign_up]': { presence: [{ message: 'must be present' }] }, + 'user[date_of_birth]': { presence: [{ message: 'must be present' }] }, + 'user[time_of_birth]': { presence: [{ message: 'must be present' }] }, } } @@ -132,7 +135,73 @@ QUnit.module('Validate Element', { id: 'customized_field', type: 'text' })) - + .append($('')) + .append($('', { + name: 'user[date_of_sign_up]', + id: 'user_date_of_sign_up', + type: 'date' + })) + .append($('')) + .append($('', { + type: 'hidden', + id: 'user_time_of_birth_1i', + name: 'user[time_of_birth(1i)]', + value: 1 + })) + .append($('', { + type: 'hidden', + id: 'user_time_of_birth_2i', + name: 'user[time_of_birth(2i)]', + value: 1 + })) + .append($('', { + type: 'hidden', + id: 'user_time_of_birth_3i', + name: 'user[time_of_birth(3i)]', + value: 1 + })) + .append($('', { + id: 'user_time_of_birth_5i', + name: 'user[time_of_birth(5i)]', + }) + .append($('')) + .append($('')) + .append($('')) + ) + .append($('')) + .append($('', { + id: 'user_date_of_birth_2i', + name: 'user[time_of_birth(2i)]', + }) + .append($('')) + .append($('')) + .append($('')) + ) + .append($('