Summary
This is a broad refactor of the form validation logic in contact.js
. Among the changes:
- Reorganized code, so that functions with similar responsibility are grouped together
- ES5-ified code, to better support IE11 users
- Code comments, to explain to maintainers and community members what the code is doing
Test plan
-
Verify that the app reports empty inputs.
- Go to the contact form on the Deploy Preview
- Try to submit an empty form
- Verify that a list of errors is appended to the DOM
- Verify that the errors read
Please provide [input label]
- Verify that those errors link back to the correct inputs
- Use a screen reader to verify that the inputs are described by their errors
-
Verify that the app reports an invalid email address
- Go to the contact form on the Deploy Preview
- Try to submit a message with a malformed email address
- Verify that an error message is appended to the DOM
- Verify that the error read
Please provide a valid entry for your email
- Verify that the error links back to the correct input
- Use a screen reader to verify that the input is described by the error message
Refactor details for nerds
This refactor introduces a minimal concept of application state.
var state = {
formErrors: {},
hasErrors: false,
};
When the validateFormFields
error finds an invalid input, information we store a reference to that input in the state
object, then use the input's label to make the message that explains the problem to the user. This message is also stored in our state
.
// inputID is the id attribute of input
state.formErrors[inputID] = {
inputEl: input,
};
if (type === 'EMPTY') {
state.formErrors[inputID].message = 'Please provide' + labelText + '.';
}
if (type === 'INVALID') {
state.formErrors[inputID].message =
'Please provide a valid entry for ' + labelText + '.';
}
By creating this single source of information, we can put all our rendering work under one function: renderErrors
. renderErrors
uses state
to build the links that point the user back to the invalid input fields, and also makes sure those inputs are marked with aria-invalid
.
Every time the user submits the form, we also call resetState
first. This removes any error information from the DOM and also from our state.
// Remove the element that shows errors to the user,
// if it exists
if (errorWrapper) {
form.removeChild(errorWrapper);
}
// Remove error attributes that may have been added on previous submit:
for (var inputID in state.formErrors) {
var input = state.formErrors[inputID].inputEl;
input.removeAttribute('aria-invalid');
input.removeAttribute('aria-describedby');
}
// Reset the application state to its default: no errors.
state.hasErrors = false;
state.formErrors = {};
Then we validate again. If there are errors, we put them in the application state and call renderErrors
. If there are no errors, the form is submitted!