Commit b98e0ebb authored by Dave Pisek's avatar Dave Pisek

Review feedback: apply suggestion, add comments

* Apply suggestion of making form-validity check more readable
* Clean up code and add comments
parent 0651053f
import { merge } from 'lodash'; import { merge } from 'lodash';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
export const defaultValidationMessages = { /**
* Validation messages will take priority based on the property order.
* For example:
* { valueMissing: {...}, urlTypeMismatch: {...} }
*
* `valueMissing` will be displayed the user has entered a value
* after that, if the input is not a valid URL then `urlTypeMismatch` will show
*/
const defaultFeedbackMap = {
valueMissing: {
isInvalid: el => el.validity?.valueMissing,
message: s__('Please fill out this field.'),
},
urlTypeMismatch: { urlTypeMismatch: {
check: el => el.type === 'url' && el.validity?.typeMismatch, isInvalid: el => el.type === 'url' && el.validity?.typeMismatch,
message: s__('Please enter a valid URL format, ex: http://www.example.com/home'), message: s__('Please enter a valid URL format, ex: http://www.example.com/home'),
}, },
}; };
const getCustomValidationMessage = (feedback, el) => const getFeedbackForElement = (feedbackMap, el) =>
Object.values(feedback).find(f => f.check(el))?.message || ''; Object.values(feedbackMap).find(f => f.isInvalid(el))?.message || el.validationMessage;
const focusFirstInvalidInput = e => { const focusFirstInvalidInput = e => {
const { target: formEl } = e; const { target: formEl } = e;
...@@ -20,23 +32,22 @@ const focusFirstInvalidInput = e => { ...@@ -20,23 +32,22 @@ const focusFirstInvalidInput = e => {
} }
}; };
const createValidator = (context, validationMessages) => el => { const isEveryFieldValid = form => Object.values(form.fields).every(({ state }) => state === true);
const createValidator = (context, feedbackMap) => el => {
const { form } = context; const { form } = context;
const { name } = el; const { name } = el;
const formField = form.fields[name];
const isValid = el.checkValidity(); const isValid = el.checkValidity();
form.fields[name].state = isValid; formField.state = isValid;
form.fields[name].feedback = formField.feedback = getFeedbackForElement(feedbackMap, el);
getCustomValidationMessage(validationMessages, el) || el.validationMessage;
form.state = !Object.values(form.fields).some(field => field.state === false); form.state = isEveryFieldValid(form);
return isValid;
}; };
export default function(customValidationMessages = {}) { export default function(customFeedbackMap = {}) {
const feedback = merge(defaultValidationMessages, customValidationMessages); const feedbackMap = merge(defaultFeedbackMap, customFeedbackMap);
const elDataMap = new WeakMap(); const elDataMap = new WeakMap();
return { return {
...@@ -44,12 +55,14 @@ export default function(customValidationMessages = {}) { ...@@ -44,12 +55,14 @@ export default function(customValidationMessages = {}) {
const { arg: showGlobalValidation } = binding; const { arg: showGlobalValidation } = binding;
const { form: formEl } = el; const { form: formEl } = el;
const validate = createValidator(context, feedback); const validate = createValidator(context, feedbackMap);
const elData = { validate, isTouched: false, isBlurred: false }; const elData = { validate, isTouched: false, isBlurred: false };
elDataMap.set(el, elData); elDataMap.set(el, elData);
el.addEventListener('input', function markAsTouched() { el.addEventListener('input', function markAsTouched() {
elData.isTouched = true; elData.isTouched = true;
// once the element has been marked as touched we can stop listening on the 'input' event
el.removeEventListener('input', markAsTouched); el.removeEventListener('input', markAsTouched);
}); });
...@@ -57,7 +70,7 @@ export default function(customValidationMessages = {}) { ...@@ -57,7 +70,7 @@ export default function(customValidationMessages = {}) {
if (elData.isTouched) { if (elData.isTouched) {
elData.isBlurred = true; elData.isBlurred = true;
validate(target); validate(target);
// this event handler can be removed, since the live-feedback now takes over // this event handler can be removed, since the live-feedback in `update` takes over
el.removeEventListener('blur', markAsBlurred); el.removeEventListener('blur', markAsBlurred);
} }
}); });
......
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