Commit ef02c5c7 authored by Dave Pisek's avatar Dave Pisek

Feedback: Make validity reporting clearer

* Renaming of parameter
* Add more comments to explain the behavior
parent ed884e74
...@@ -3,6 +3,7 @@ import { s__ } from '~/locale'; ...@@ -3,6 +3,7 @@ import { s__ } from '~/locale';
/** /**
* Validation messages will take priority based on the property order. * Validation messages will take priority based on the property order.
*
* For example: * For example:
* { valueMissing: {...}, urlTypeMismatch: {...} } * { valueMissing: {...}, urlTypeMismatch: {...} }
* *
...@@ -34,7 +35,7 @@ const focusFirstInvalidInput = e => { ...@@ -34,7 +35,7 @@ const focusFirstInvalidInput = e => {
const isEveryFieldValid = form => Object.values(form.fields).every(({ state }) => state === true); const isEveryFieldValid = form => Object.values(form.fields).every(({ state }) => state === true);
const createValidator = (context, feedbackMap) => ({ el, reportValidity = false }) => { const createValidator = (context, feedbackMap) => ({ el, reportInvalidInput = false }) => {
const { form } = context; const { form } = context;
const { name } = el; const { name } = el;
...@@ -51,26 +52,38 @@ const createValidator = (context, feedbackMap) => ({ el, reportValidity = false ...@@ -51,26 +52,38 @@ const createValidator = (context, feedbackMap) => ({ el, reportValidity = false
const formField = form.fields[name]; const formField = form.fields[name];
const isValid = el.checkValidity(); const isValid = el.checkValidity();
// valid fields can be flagged as such, without triggering any validation feedback (messages, input-styles) // This makes sure we always report valid fields - this can be useful for cases where the consuming
formField.state = !reportValidity && !isValid ? null : isValid; // component's logic depends on certain fields being in a valid state.
formField.feedback = reportValidity ? getFeedbackForElement(feedbackMap, el) : ''; // Invalid input, on the other hand, should only be reported once we want to display feedback to the user.
// (eg.: After a field has been touched and moved away from, a submit-button has been clicked, ...)
formField.state = reportInvalidInput ? isValid : isValid || null;
formField.feedback = reportInvalidInput ? getFeedbackForElement(feedbackMap, el) : '';
form.state = isEveryFieldValid(form); form.state = isEveryFieldValid(form);
}; };
/** /**
* Takes an object that allows to add or change custom feedback messages: * Takes an object that allows to add or change custom feedback messages.
*
* The passed in object will be merged with the built-in feedback
* so it is possible to override a built-in message.
* *
* @example
* validate({
* tooLong: {
* check: el => el.validity.tooLong === true,
* message: 'Your custom feedback'
* }
* })
*
* @example
* validate({ * validate({
* tooLong: { * valueMissing: {
* check: el => el.validity.tooLong === true, * message: 'Your custom feedback'
* message: 'The value you have entered is too long'
* } * }
* }) * })
* *
* Note: The passed in object will be merged with the built-in feedback. * @param {Object<string, { message: string, isValid: ?function}>} customFeedbackMap
*
* @param {Object<string, {isValid: function, message: string}>} customFeedbackMap
* @returns {{ inserted: function, update: function }} validateDirective * @returns {{ inserted: function, update: function }} validateDirective
*/ */
export default function(customFeedbackMap = {}) { export default function(customFeedbackMap = {}) {
...@@ -96,7 +109,7 @@ export default function(customFeedbackMap = {}) { ...@@ -96,7 +109,7 @@ export default function(customFeedbackMap = {}) {
el.addEventListener('blur', function markAsBlurred({ target }) { el.addEventListener('blur', function markAsBlurred({ target }) {
if (elData.isTouched) { if (elData.isTouched) {
elData.isBlurred = true; elData.isBlurred = true;
validate({ el: target, reportValidity: true }); validate({ el: target, reportInvalidInput: true });
// this event handler can be removed, since the live-feedback in `update` takes over // this event handler can be removed, since the live-feedback in `update` takes over
el.removeEventListener('blur', markAsBlurred); el.removeEventListener('blur', markAsBlurred);
} }
...@@ -106,14 +119,14 @@ export default function(customFeedbackMap = {}) { ...@@ -106,14 +119,14 @@ export default function(customFeedbackMap = {}) {
formEl.addEventListener('submit', focusFirstInvalidInput); formEl.addEventListener('submit', focusFirstInvalidInput);
} }
validate({ el, reportValidity: showGlobalValidation }); validate({ el, reportInvalidInput: showGlobalValidation });
}, },
update(el, binding) { update(el, binding) {
const { arg: showGlobalValidation } = binding; const { arg: showGlobalValidation } = binding;
const { validate, isTouched, isBlurred } = elDataMap.get(el); const { validate, isTouched, isBlurred } = elDataMap.get(el);
const showValidationFeedback = showGlobalValidation || (isTouched && isBlurred); const showValidationFeedback = showGlobalValidation || (isTouched && isBlurred);
validate({ el, reportValidity: showValidationFeedback }); validate({ el, reportInvalidInput: showValidationFeedback });
}, },
}; };
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment