From 5eac68172d86e27e8cbc0e76cf3ffc007b8e63f0 Mon Sep 17 00:00:00 2001 From: soylent Date: Sat, 23 Feb 2019 18:08:40 -0700 Subject: [PATCH] feat(abide): add validator-specific error messages Now you can add different error messages for each validator using the `[data-form-error-on]` attribute. Required Invalid BREAKING CHANGE: `Foundation.Abide#validateText()` no longer checks if the input is required. Use the `Foundation.Abide#requiredCheck()` method for that. Closes #10799 --- docs/pages/abide.md | 22 +++++ js/foundation.abide.js | 64 ++++++++------ test/visual/abide/error-messages.html | 120 ++++++++++++++++++++++++++ 3 files changed, 181 insertions(+), 25 deletions(-) create mode 100644 test/visual/abide/error-messages.html diff --git a/docs/pages/abide.md b/docs/pages/abide.md index e31789601..2033f3041 100644 --- a/docs/pages/abide.md +++ b/docs/pages/abide.md @@ -168,6 +168,28 @@ When the Form Errors cannot be placed next to its field, like in an Input Group, ``` +You can specify validator-specific error messages using `[data-form-error-on]` +attribute, for example: + +- `data-form-error-on="required"` +- `data-form-error-on="pattern"` +- `data-form-error-on="equalTo"` +- `data-form-error-on="your_custom_validator"` + +```html_example +
+ + +
+``` ## Initial State diff --git a/js/foundation.abide.js b/js/foundation.abide.js index 7fbd9df8d..2fadf6ab4 100644 --- a/js/foundation.abide.js +++ b/js/foundation.abide.js @@ -173,9 +173,10 @@ class Abide extends Plugin { * This allows for multiple form errors per input, though if none are found, no form errors will be shown. * * @param {Object} $el - jQuery object to use as reference to find the form error selector. + * @param {String[]} [failedValidators] - List of failed validators. * @returns {Object} jQuery object with the selector. */ - findFormError($el) { + findFormError($el, failedValidators) { var id = $el.length ? $el[0].id : ''; var $error = $el.siblings(this.options.formErrorSelector); @@ -187,6 +188,15 @@ class Abide extends Plugin { $error = $error.add(this.$element.find(`[data-form-error-for="${id}"]`)); } + if (!!failedValidators) { + $error = $error.not('[data-form-error-on]') + + failedValidators.forEach((v) => { + $error = $error.add($el.siblings(`[data-form-error-on="${v}"]`)); + $error = $error.add(this.$element.find(`[data-form-error-for="${id}"][data-form-error-on="${v}"]`)); + }); + } + return $error; } @@ -256,10 +266,11 @@ class Abide extends Plugin { /** * Adds the CSS error class as specified by the Abide settings to the label, input, and the form * @param {Object} $el - jQuery object to add the class to + * @param {String[]} [failedValidators] - List of failed validators. */ - addErrorClasses($el) { + addErrorClasses($el, failedValidators) { var $label = this.findLabel($el); - var $formError = this.findFormError($el); + var $formError = this.findFormError($el, failedValidators); if ($label.length) { $label.addClass(this.options.labelErrorClass); @@ -422,10 +433,9 @@ class Abide extends Plugin { */ validateInput($el) { var clearRequire = this.requiredCheck($el), - validated = false, - customValidator = true, validator = $el.attr('data-validator'), - equalTo = true; + failedValidators = [], + manageErrorClasses = true; // skip validation if disabled if (this._validationIsDisabled()) { @@ -439,34 +449,39 @@ class Abide extends Plugin { switch ($el[0].type) { case 'radio': - validated = this.validateRadio($el.attr('name')); + this.validateRadio($el.attr('name')) || failedValidators.push('required'); break; case 'checkbox': - validated = this.validateCheckbox($el.attr('name')); - clearRequire = true; + this.validateCheckbox($el.attr('name')) || failedValidators.push('required'); + // validateCheckbox() adds/removes error classes + manageErrorClasses = false; break; case 'select': case 'select-one': case 'select-multiple': - validated = clearRequire; + clearRequire || failedValidators.push('required'); break; default: - validated = this.validateText($el); + clearRequire || failedValidators.push('required'); + this.validateText($el) || failedValidators.push('pattern'); } if (validator) { - customValidator = this.matchValidation($el, validator, $el.attr('required')); + const required = $el.attr('required') ? true : false; + + validator.split(' ').forEach((v) => { + this.options.validators[v]($el, required, $el.parent()) || failedValidators.push(v); + }); } if ($el.attr('data-equalto')) { - equalTo = this.options.validators.equalTo($el); + this.options.validators.equalTo($el) || failedValidators.push('equalTo'); } - - var goodToGo = [clearRequire, validated, customValidator, equalTo].indexOf(false) === -1; + var goodToGo = failedValidators.length === 0; var message = (goodToGo ? 'valid' : 'invalid') + '.zf.abide'; if (goodToGo) { @@ -482,7 +497,13 @@ class Abide extends Plugin { } } - this[goodToGo ? 'removeErrorClasses' : 'addErrorClasses']($el); + if (manageErrorClasses) { + this.removeErrorClasses($el); + + if (!goodToGo) { + this.addErrorClasses($el, failedValidators); + } + } /** * Fires when the input is done checking for validation. Event trigger is either `valid.zf.abide` or `invalid.zf.abide` @@ -559,7 +580,7 @@ class Abide extends Plugin { // A pattern can be passed to this function, or it will be infered from the input's "pattern" attribute, or it's "type" attribute pattern = (pattern || $el.attr('data-pattern') || $el.attr('pattern') || $el.attr('type')); var inputText = $el.val(); - var valid = false; + var valid = true; if (inputText.length) { // If the pattern attribute on the element is in Abide's list of patterns, then test that regexp @@ -570,13 +591,6 @@ class Abide extends Plugin { else if (pattern !== $el.attr('type')) { valid = new RegExp(pattern).test(inputText); } - else { - valid = true; - } - } - // An empty field is valid if it's not required - else if (!$el.prop('required')) { - valid = true; } return valid; @@ -658,7 +672,7 @@ class Abide extends Plugin { // Refresh error class for all input $group.each((i, e) => { if (!valid) { - this.addErrorClasses($(e)); + this.addErrorClasses($(e), ['required']); } else { this.removeErrorClasses($(e)); } diff --git a/test/visual/abide/error-messages.html b/test/visual/abide/error-messages.html new file mode 100644 index 000000000..d35e1fef8 --- /dev/null +++ b/test/visual/abide/error-messages.html @@ -0,0 +1,120 @@ + + + + + + + + Foundation for Sites Testing + + + +
+
+
+

Abide: Error Messages

+ +

This form has two different error messages.

+ +
+ + + +
+ +
+ +

This form has two different error messages and uses the [data-form-error-for] attribute to specify the target input.

+ +
+ + Required + Invalid + + +
+ +
+ +

This form has one generic and one validator-specific error message.

+ +
+ + + +
+ +
+ +

This form uses the equalTo validator.

+ +
+ + + + Invalid + Mismatch + + + +
+ +
+ +

This form has two input fields.

+ +
+ + + + +
+ +
+ +

This form uses a custom validator.

+ +
+ + + +
+
+
+
+ + + + + + -- 2.47.2