Skip to content

Commit

Permalink
Implemented field's specific wrapper_names to be passed to and used b…
Browse files Browse the repository at this point in the history
…y 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`
  • Loading branch information
MichalRemis committed Apr 28, 2020
1 parent 2638bf2 commit 3996907
Show file tree
Hide file tree
Showing 12 changed files with 107 additions and 20 deletions.
7 changes: 5 additions & 2 deletions dist/simple-form.bootstrap4.esm.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,17 @@ import ClientSideValidations from '@client-side-validations/client-side-validati

ClientSideValidations.formBuilders['SimpleForm::FormBuilder'] = {
add: function add(element, settings, message) {
this.wrapper(settings.wrapper).add.call(this, element, settings, message);
this.wrapper(this.wrapperName(element, settings)).add.call(this, element, settings, message);
},
remove: function remove(element, settings) {
this.wrapper(settings.wrapper).remove.call(this, element, settings);
this.wrapper(this.wrapperName(element, settings)).remove.call(this, element, settings);
},
wrapper: function wrapper(name) {
return this.wrappers[name] || this.wrappers["default"];
},
wrapperName: function wrapperName(element, settings) {
return element.data('clientSideValidationsWrapper') || settings.wrapper;
},
wrappers: {
"default": {
add: function add(element, settings, message) {
Expand Down
7 changes: 5 additions & 2 deletions dist/simple-form.bootstrap4.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,17 @@

ClientSideValidations.formBuilders['SimpleForm::FormBuilder'] = {
add: function add(element, settings, message) {
this.wrapper(settings.wrapper).add.call(this, element, settings, message);
this.wrapper(this.wrapperName(element, settings)).add.call(this, element, settings, message);
},
remove: function remove(element, settings) {
this.wrapper(settings.wrapper).remove.call(this, element, settings);
this.wrapper(this.wrapperName(element, settings)).remove.call(this, element, settings);
},
wrapper: function wrapper(name) {
return this.wrappers[name] || this.wrappers["default"];
},
wrapperName: function wrapperName(element, settings) {
return element.data('clientSideValidationsWrapper') || settings.wrapper;
},
wrappers: {
"default": {
add: function add(element, settings, message) {
Expand Down
7 changes: 5 additions & 2 deletions dist/simple-form.esm.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,17 @@ import ClientSideValidations from '@client-side-validations/client-side-validati

ClientSideValidations.formBuilders['SimpleForm::FormBuilder'] = {
add: function add(element, settings, message) {
this.wrapper(settings.wrapper).add.call(this, element, settings, message);
this.wrapper(this.wrapperName(element, settings)).add.call(this, element, settings, message);
},
remove: function remove(element, settings) {
this.wrapper(settings.wrapper).remove.call(this, element, settings);
this.wrapper(this.wrapperName(element, settings)).remove.call(this, element, settings);
},
wrapper: function wrapper(name) {
return this.wrappers[name] || this.wrappers["default"];
},
wrapperName: function wrapperName(element, settings) {
return element.data('clientSideValidationsWrapper') || settings.wrapper;
},
wrappers: {
"default": {
add: function add(element, settings, message) {
Expand Down
7 changes: 5 additions & 2 deletions dist/simple-form.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,17 @@

ClientSideValidations.formBuilders['SimpleForm::FormBuilder'] = {
add: function add(element, settings, message) {
this.wrapper(settings.wrapper).add.call(this, element, settings, message);
this.wrapper(this.wrapperName(element, settings)).add.call(this, element, settings, message);
},
remove: function remove(element, settings) {
this.wrapper(settings.wrapper).remove.call(this, element, settings);
this.wrapper(this.wrapperName(element, settings)).remove.call(this, element, settings);
},
wrapper: function wrapper(name) {
return this.wrappers[name] || this.wrappers["default"];
},
wrapperName: function wrapperName(element, settings) {
return element.data('clientSideValidationsWrapper') || settings.wrapper;
},
wrappers: {
"default": {
add: function add(element, settings, message) {
Expand Down
10 changes: 10 additions & 0 deletions lib/client_side_validations/simple_form/form_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ def input(attribute_name, options = {}, &block)
options.delete(:validate)
end

add_field_specific_wrapper_name_to_field_options(attribute_name, options, &block)

super(attribute_name, options, &block)
end

Expand All @@ -34,6 +36,14 @@ def wrapper_error_component
wrapper.find(:full_error)
end
end

def add_field_specific_wrapper_name_to_field_options(attribute_name, options, &block)
wrapper_name = options[:wrapper] || find_wrapper_mapping(find_input(attribute_name, options, &block).input_type)
return if wrapper_name.nil?

options[:input_html] ||= {}
options[:input_html][:'data-client-side-validations-wrapper'] = wrapper_name
end
end
end
end
Expand Down
9 changes: 6 additions & 3 deletions src/main.bootstrap4.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,23 @@ import ClientSideValidations from '@client-side-validations/client-side-validati

ClientSideValidations.formBuilders['SimpleForm::FormBuilder'] = {
add: function (element, settings, message) {
this.wrapper(settings.wrapper).add.call(this, element, settings, message)
this.wrapper(this.wrapperName(element, settings)).add.call(this, element, settings, message)
},
remove: function (element, settings) {
this.wrapper(settings.wrapper).remove.call(this, element, settings)
this.wrapper(this.wrapperName(element, settings)).remove.call(this, element, settings)
},
wrapper: function (name) {
return this.wrappers[name] || this.wrappers.default
},
wrapperName: function (element, settings) {
return element.data('clientSideValidationsWrapper') || settings.wrapper
},

wrappers: {
default: {
add (element, settings, message) {
const wrapperElement = element.parent()
let errorElement = wrapperElement.find(settings.error_tag + '.invalid-feedback')
var errorElement = wrapperElement.find(settings.error_tag + '.invalid-feedback')

if (!errorElement.length) {
errorElement = $('<' + settings.error_tag + '>', { class: 'invalid-feedback', text: message })
Expand Down
9 changes: 6 additions & 3 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,23 @@ import ClientSideValidations from '@client-side-validations/client-side-validati

ClientSideValidations.formBuilders['SimpleForm::FormBuilder'] = {
add: function (element, settings, message) {
this.wrapper(settings.wrapper).add.call(this, element, settings, message)
this.wrapper(this.wrapperName(element, settings)).add.call(this, element, settings, message)
},
remove: function (element, settings) {
this.wrapper(settings.wrapper).remove.call(this, element, settings)
this.wrapper(this.wrapperName(element, settings)).remove.call(this, element, settings)
},
wrapper: function (name) {
return this.wrappers[name] || this.wrappers.default
},
wrapperName: function (element, settings) {
return element.data('clientSideValidationsWrapper') || settings.wrapper
},

wrappers: {
default: {
add (element, settings, message) {
const wrapper = element.closest(settings.wrapper_tag + '.' + settings.wrapper_class.replace(/ /g, '.'))
let errorElement = wrapper.find(settings.error_tag + '.' + settings.error_class.replace(/ /g, '.'))
var errorElement = wrapper.find(settings.error_tag + '.' + settings.error_class.replace(/ /g, '.'))

if (!errorElement.length) {
errorElement = $('<' + settings.error_tag + '>', { class: settings.error_class, text: message })
Expand Down
28 changes: 27 additions & 1 deletion test/javascript/public/test/form_builders/validateSimpleForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ QUnit.module('Validate SimpleForm', {
wrapper: 'default'
},
validators: {
'user[name]': { presence: [{ message: 'must be present' }], format: [{ message: 'is invalid', 'with': { options: 'g', source: '\\d+' } }] }
'user[name]': { presence: [{ message: 'must be present' }], format: [{ message: 'is invalid', 'with': { options: 'g', source: '\\d+' } }] },
'user[date_of_birth]': { presence: [{ message: 'must be present' }] }
}
}

Expand All @@ -40,6 +41,12 @@ QUnit.module('Validate SimpleForm', {
type: 'text'
}))
.append($('<label for="user_name">Name</label>'))
.append($('<input />', {
name: 'user[date_of_birth]',
id: 'date_of_birth',
type: 'text',
'data-client-side-validations-wrapper': 'custom_date_wrapper'
}))
$('form#new_user').validate()
}
})
Expand Down Expand Up @@ -82,3 +89,22 @@ QUnit.test('Validate pre-existing error blocks are re-used', function (assert) {
assert.ok(input.parent().find('span.error:contains("is invalid")').length === 1)
assert.ok(form.find('span.error').length === 1)
})

QUnit.test('Validate correct JS Builder\'s wrapper is called for custom_wrapper', function (assert) {
const oldWrappers = $.extend({}, ClientSideValidations.formBuilders['SimpleForm::FormBuilder'].wrappers)

// It would be probably better to use some stub library but I want to keep it simple
let customWrapperCalled = false;

ClientSideValidations.formBuilders['SimpleForm::FormBuilder'].wrappers['custom_date_wrapper'] = {
add: function(element, settings, message) { customWrapperCalled=true; },
remove: function(element, settings) {}
}

var form = $('form#new_user');
var input = form.find('input#date_of_birth')
input.trigger('focusout')

assert.ok(customWrapperCalled);
ClientSideValidations.formBuilders['SimpleForm::FormBuilder'].wrappers = oldWrappers
})
24 changes: 24 additions & 0 deletions test/simple_form/cases/test_form_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,30 @@ def test_input_override

assert_dom_equal expected, output_buffer
end

def test_input_override_with_custom_wrapper_name
simple_form_for(@post, validate: true, wrapper: :default) do |f|
concat f.input(:cost, validate: false, wrapper: :custom_date_wrapper)
end

csv_data = {
html_settings: {
type: 'SimpleForm::FormBuilder',
error_class: 'error',
error_tag: 'span',
wrapper_error_class: 'field_with_errors',
wrapper_tag: 'div',
wrapper_class: 'input',
wrapper: 'default'
},
number_format: { separator: '.', delimiter: ',' },
validators: {}
}

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>)

assert_dom_equal expected, output_buffer
end
end
end
end
5 changes: 4 additions & 1 deletion test/test_loader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
require 'base_helper'
require 'client_side_validations/simple_form'

SimpleForm.setup do
SimpleForm.setup do |config|
config.wrappers :custom_date_wrapper, tag: 'div' do |b|
b.use :input, class: 'form-control'
end
end

TestApp::Application.initialize!
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,17 @@

ClientSideValidations.formBuilders['SimpleForm::FormBuilder'] = {
add: function add(element, settings, message) {
this.wrapper(settings.wrapper).add.call(this, element, settings, message);
this.wrapper(this.wrapperName(element, settings)).add.call(this, element, settings, message);
},
remove: function remove(element, settings) {
this.wrapper(settings.wrapper).remove.call(this, element, settings);
this.wrapper(this.wrapperName(element, settings)).remove.call(this, element, settings);
},
wrapper: function wrapper(name) {
return this.wrappers[name] || this.wrappers["default"];
},
wrapperName: function wrapperName(element, settings) {
return element.data('clientSideValidationsWrapper') || settings.wrapper;
},
wrappers: {
"default": {
add: function add(element, settings, message) {
Expand Down
7 changes: 5 additions & 2 deletions vendor/assets/javascripts/rails.validations.simple_form.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,17 @@

ClientSideValidations.formBuilders['SimpleForm::FormBuilder'] = {
add: function add(element, settings, message) {
this.wrapper(settings.wrapper).add.call(this, element, settings, message);
this.wrapper(this.wrapperName(element, settings)).add.call(this, element, settings, message);
},
remove: function remove(element, settings) {
this.wrapper(settings.wrapper).remove.call(this, element, settings);
this.wrapper(this.wrapperName(element, settings)).remove.call(this, element, settings);
},
wrapper: function wrapper(name) {
return this.wrappers[name] || this.wrappers["default"];
},
wrapperName: function wrapperName(element, settings) {
return element.data('clientSideValidationsWrapper') || settings.wrapper;
},
wrappers: {
"default": {
add: function add(element, settings, message) {
Expand Down

0 comments on commit 3996907

Please sign in to comment.