Skip to content

Commit 1d5da93

Browse files
committed
Implemented field's specific wrapper_names to be passed to and used by CSV Javascript form builder for adding/removing of error messages. Before CSV used only form-wide wrapper but field may use custom wrapper specified:
- by field's `wrapper` attribute - by field's type and `wrapper_mappings` attribute - by field's type and SimpleForm config `wrapper_mappings`
1 parent f950d7f commit 1d5da93

File tree

12 files changed

+105
-18
lines changed

12 files changed

+105
-18
lines changed

dist/simple-form.bootstrap4.esm.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,17 @@ import ClientSideValidations from '@client-side-validations/client-side-validati
99

1010
ClientSideValidations.formBuilders['SimpleForm::FormBuilder'] = {
1111
add: function add(element, settings, message) {
12-
this.wrapper(settings.wrapper).add.call(this, element, settings, message);
12+
this.wrapper(this.wrapperName(element, settings)).add.call(this, element, settings, message);
1313
},
1414
remove: function remove(element, settings) {
15-
this.wrapper(settings.wrapper).remove.call(this, element, settings);
15+
this.wrapper(this.wrapperName(element, settings)).remove.call(this, element, settings);
1616
},
1717
wrapper: function wrapper(name) {
1818
return this.wrappers[name] || this.wrappers["default"];
1919
},
20+
wrapperName: function wrapperName(element, settings) {
21+
return element.data('clientSideValidationsWrapper') || settings.wrapper;
22+
},
2023
wrappers: {
2124
"default": {
2225
add: function add(element, settings, message) {

dist/simple-form.bootstrap4.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,17 @@
1515

1616
ClientSideValidations.formBuilders['SimpleForm::FormBuilder'] = {
1717
add: function add(element, settings, message) {
18-
this.wrapper(settings.wrapper).add.call(this, element, settings, message);
18+
this.wrapper(this.wrapperName(element, settings)).add.call(this, element, settings, message);
1919
},
2020
remove: function remove(element, settings) {
21-
this.wrapper(settings.wrapper).remove.call(this, element, settings);
21+
this.wrapper(this.wrapperName(element, settings)).remove.call(this, element, settings);
2222
},
2323
wrapper: function wrapper(name) {
2424
return this.wrappers[name] || this.wrappers["default"];
2525
},
26+
wrapperName: function wrapperName(element, settings) {
27+
return element.data('clientSideValidationsWrapper') || settings.wrapper;
28+
},
2629
wrappers: {
2730
"default": {
2831
add: function add(element, settings, message) {

dist/simple-form.esm.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,17 @@ import ClientSideValidations from '@client-side-validations/client-side-validati
99

1010
ClientSideValidations.formBuilders['SimpleForm::FormBuilder'] = {
1111
add: function add(element, settings, message) {
12-
this.wrapper(settings.wrapper).add.call(this, element, settings, message);
12+
this.wrapper(this.wrapperName(element, settings)).add.call(this, element, settings, message);
1313
},
1414
remove: function remove(element, settings) {
15-
this.wrapper(settings.wrapper).remove.call(this, element, settings);
15+
this.wrapper(this.wrapperName(element, settings)).remove.call(this, element, settings);
1616
},
1717
wrapper: function wrapper(name) {
1818
return this.wrappers[name] || this.wrappers["default"];
1919
},
20+
wrapperName: function wrapperName(element, settings) {
21+
return element.data('clientSideValidationsWrapper') || settings.wrapper;
22+
},
2023
wrappers: {
2124
"default": {
2225
add: function add(element, settings, message) {

dist/simple-form.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,17 @@
1515

1616
ClientSideValidations.formBuilders['SimpleForm::FormBuilder'] = {
1717
add: function add(element, settings, message) {
18-
this.wrapper(settings.wrapper).add.call(this, element, settings, message);
18+
this.wrapper(this.wrapperName(element, settings)).add.call(this, element, settings, message);
1919
},
2020
remove: function remove(element, settings) {
21-
this.wrapper(settings.wrapper).remove.call(this, element, settings);
21+
this.wrapper(this.wrapperName(element, settings)).remove.call(this, element, settings);
2222
},
2323
wrapper: function wrapper(name) {
2424
return this.wrappers[name] || this.wrappers["default"];
2525
},
26+
wrapperName: function wrapperName(element, settings) {
27+
return element.data('clientSideValidationsWrapper') || settings.wrapper;
28+
},
2629
wrappers: {
2730
"default": {
2831
add: function add(element, settings, message) {

lib/client_side_validations/simple_form/form_builder.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ def input(attribute_name, options = {}, &block)
2222
options.delete(:validate)
2323
end
2424

25+
add_field_specific_wrapper_name_to_field_options(attribute_name, options, &block)
26+
2527
super(attribute_name, options, &block)
2628
end
2729

@@ -34,6 +36,14 @@ def wrapper_error_component
3436
wrapper.find(:full_error)
3537
end
3638
end
39+
40+
def add_field_specific_wrapper_name_to_field_options(attribute_name, options, &block)
41+
wrapper_name = options[:wrapper] || find_wrapper_mapping(find_input(attribute_name, options, &block).input_type)
42+
return if wrapper_name.nil?
43+
44+
options[:input_html] ||= {}
45+
options[:input_html][:'data-client-side-validations-wrapper'] = wrapper_name
46+
end
3747
end
3848
end
3949
end

src/main.bootstrap4.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,17 @@ import ClientSideValidations from '@client-side-validations/client-side-validati
33

44
ClientSideValidations.formBuilders['SimpleForm::FormBuilder'] = {
55
add: function (element, settings, message) {
6-
this.wrapper(settings.wrapper).add.call(this, element, settings, message)
6+
this.wrapper(this.wrapperName(element, settings)).add.call(this, element, settings, message)
77
},
88
remove: function (element, settings) {
9-
this.wrapper(settings.wrapper).remove.call(this, element, settings)
9+
this.wrapper(this.wrapperName(element, settings)).remove.call(this, element, settings)
1010
},
1111
wrapper: function (name) {
1212
return this.wrappers[name] || this.wrappers.default
1313
},
14+
wrapperName: function (element, settings) {
15+
return element.data('clientSideValidationsWrapper') || settings.wrapper
16+
},
1417

1518
wrappers: {
1619
default: {

src/main.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,17 @@ import ClientSideValidations from '@client-side-validations/client-side-validati
33

44
ClientSideValidations.formBuilders['SimpleForm::FormBuilder'] = {
55
add: function (element, settings, message) {
6-
this.wrapper(settings.wrapper).add.call(this, element, settings, message)
6+
this.wrapper(this.wrapperName(element, settings)).add.call(this, element, settings, message)
77
},
88
remove: function (element, settings) {
9-
this.wrapper(settings.wrapper).remove.call(this, element, settings)
9+
this.wrapper(this.wrapperName(element, settings)).remove.call(this, element, settings)
1010
},
1111
wrapper: function (name) {
1212
return this.wrappers[name] || this.wrappers.default
1313
},
14+
wrapperName: function (element, settings) {
15+
return element.data('clientSideValidationsWrapper') || settings.wrapper
16+
},
1417

1518
wrappers: {
1619
default: {

test/javascript/public/test/form_builders/validateSimpleForm.js

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ QUnit.module('Validate SimpleForm', {
2020
wrapper: 'default'
2121
},
2222
validators: {
23-
'user[name]': { presence: [{ message: 'must be present' }], format: [{ message: 'is invalid', 'with': { options: 'g', source: '\\d+' } }] }
23+
'user[name]': { presence: [{ message: 'must be present' }], format: [{ message: 'is invalid', 'with': { options: 'g', source: '\\d+' } }] },
24+
'user[date_of_birth]': { presence: [{ message: 'must be present' }] }
2425
}
2526
}
2627

@@ -40,6 +41,12 @@ QUnit.module('Validate SimpleForm', {
4041
type: 'text'
4142
}))
4243
.append($('<label for="user_name">Name</label>'))
44+
.append($('<input />', {
45+
name: 'user[date_of_birth]',
46+
id: 'date_of_birth',
47+
type: 'text',
48+
'data-client-side-validations-wrapper': 'custom_date_wrapper'
49+
}))
4350
$('form#new_user').validate()
4451
}
4552
})
@@ -82,3 +89,22 @@ QUnit.test('Validate pre-existing error blocks are re-used', function (assert) {
8289
assert.ok(input.parent().find('span.error:contains("is invalid")').length === 1)
8390
assert.ok(form.find('span.error').length === 1)
8491
})
92+
93+
QUnit.test('Validate correct JS Builder\'s wrapper is called for custom_wrapper', function (assert) {
94+
const oldWrappers = $.extend({}, ClientSideValidations.formBuilders['SimpleForm::FormBuilder'].wrappers)
95+
96+
// It would be probably better to use some stub library but I want to keep it simple
97+
let customWrapperCalled = false;
98+
99+
ClientSideValidations.formBuilders['SimpleForm::FormBuilder'].wrappers['custom_date_wrapper'] = {
100+
add: function(element, settings, message) { customWrapperCalled=true; },
101+
remove: function(element, settings) {}
102+
}
103+
104+
var form = $('form#new_user');
105+
var input = form.find('input#date_of_birth')
106+
input.trigger('focusout')
107+
108+
assert.ok(customWrapperCalled);
109+
ClientSideValidations.formBuilders['SimpleForm::FormBuilder'].wrappers = oldWrappers
110+
})

test/simple_form/cases/test_form_helpers.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,30 @@ def test_input_override
102102

103103
assert_dom_equal expected, output_buffer
104104
end
105+
106+
def test_input_override_with_custom_wrapper_name
107+
simple_form_for(@post, validate: true, wrapper: :default) do |f|
108+
concat f.input(:cost, validate: false, wrapper: :custom_date_wrapper)
109+
end
110+
111+
csv_data = {
112+
html_settings: {
113+
type: 'SimpleForm::FormBuilder',
114+
error_class: 'error',
115+
error_tag: 'span',
116+
wrapper_error_class: 'field_with_errors',
117+
wrapper_tag: 'div',
118+
wrapper_class: 'input',
119+
wrapper: 'default'
120+
},
121+
number_format: { separator: '.', delimiter: ',' },
122+
validators: {}
123+
}
124+
125+
expected = %(<form accept-charset="UTF-8" action="/posts" class="simple_form new_post" data-client-side-validations="#{CGI.escapeHTML(csv_data.to_json)}" id="new_post" method="post" novalidate="novalidate"><input name="utf8" type="hidden" value="&#x2713;" /><div class="string required post_cost"><input class="form-control string required" data-client-side-validations-wrapper="custom_date_wrapper" type="text" name="post[cost]" id="post_cost" /></div></form>)
126+
127+
assert_dom_equal expected, output_buffer
128+
end
105129
end
106130
end
107131
end

test/test_loader.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
require 'base_helper'
66
require 'client_side_validations/simple_form'
77

8-
SimpleForm.setup do
8+
SimpleForm.setup do |config|
9+
config.wrappers :custom_date_wrapper, tag: 'div' do |b|
10+
b.use :input, class: 'form-control'
11+
end
912
end
1013

1114
TestApp::Application.initialize!

vendor/assets/javascripts/rails.validations.simple_form.bootstrap4.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,17 @@
1515

1616
ClientSideValidations.formBuilders['SimpleForm::FormBuilder'] = {
1717
add: function add(element, settings, message) {
18-
this.wrapper(settings.wrapper).add.call(this, element, settings, message);
18+
this.wrapper(this.wrapperName(element, settings)).add.call(this, element, settings, message);
1919
},
2020
remove: function remove(element, settings) {
21-
this.wrapper(settings.wrapper).remove.call(this, element, settings);
21+
this.wrapper(this.wrapperName(element, settings)).remove.call(this, element, settings);
2222
},
2323
wrapper: function wrapper(name) {
2424
return this.wrappers[name] || this.wrappers["default"];
2525
},
26+
wrapperName: function wrapperName(element, settings) {
27+
return element.data('clientSideValidationsWrapper') || settings.wrapper;
28+
},
2629
wrappers: {
2730
"default": {
2831
add: function add(element, settings, message) {

vendor/assets/javascripts/rails.validations.simple_form.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,17 @@
1515

1616
ClientSideValidations.formBuilders['SimpleForm::FormBuilder'] = {
1717
add: function add(element, settings, message) {
18-
this.wrapper(settings.wrapper).add.call(this, element, settings, message);
18+
this.wrapper(this.wrapperName(element, settings)).add.call(this, element, settings, message);
1919
},
2020
remove: function remove(element, settings) {
21-
this.wrapper(settings.wrapper).remove.call(this, element, settings);
21+
this.wrapper(this.wrapperName(element, settings)).remove.call(this, element, settings);
2222
},
2323
wrapper: function wrapper(name) {
2424
return this.wrappers[name] || this.wrappers["default"];
2525
},
26+
wrapperName: function wrapperName(element, settings) {
27+
return element.data('clientSideValidationsWrapper') || settings.wrapper;
28+
},
2629
wrappers: {
2730
"default": {
2831
add: function add(element, settings, message) {

0 commit comments

Comments
 (0)