Created
December 18, 2017 12:21
-
-
Save chris-kobrzak/2a730145deb2775094201bb269967e56 to your computer and use it in GitHub Desktop.
Form validation logic that can be plugged to React event handlers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Low-level, generic validation functions | |
// Signature: any => boolean | |
const hasLength = value => value.length > 0 | |
const hasLettersAndDotsOnly = value => ( | |
value.match(/^[a-z\.]+$/gi) !== null | |
) | |
/* | |
Map input fields to "types" that we want to validate in a certain way. This | |
will become more useful e.g. when we have two address forms on a page (and | |
presumably apply the same rules to them). | |
The values are referenced in inputTypeToValidations's top level keys. | |
*/ | |
const inputTypeToName = { | |
personTitle: 'title', | |
firstName: 'firstName', | |
lastName: 'lastName' | |
} | |
// Generic validation messages store | |
const message = { | |
specialCharacter: 'You can only use letters here' | |
} | |
const inputTypeToValidations = { | |
// Array here as the order of validation messages matters | |
title: [ | |
{ hasLength: 'Please enter your title' }, | |
{ hasLettersAndDotsOnly: message.specialCharacter } | |
] | |
} | |
// hasLength references validation message keys in `inputTypeToValidations` above | |
const validationRuleToMethod = { | |
hasLength, | |
hasLettersAndDotsOnly | |
} | |
function validateInput (name, value) { | |
// Methods or functions instead of dictionaries? | |
const inputType = inputTypeToName[name] | |
const validations = inputTypeToValidations[inputType] | |
for (let validation of validations) { | |
const [ rule ] = Object.keys(validation) | |
const validate = validationRuleToMethod[rule] | |
if (! validate) { | |
continue | |
} | |
// The actual validation method call | |
const valid = validate(value) | |
if (valid) { | |
// Only concerned with the first validation error | |
continue | |
} | |
return { valid, rule, message: validation[rule] } | |
} | |
return { valid: true } | |
} | |
console.log( | |
validateInput('personTitle', ''), | |
validateInput('personTitle', '_'), | |
validateInput('personTitle', 'Mrs.') | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is a simple form validation collaborator pattern that can be plugged into React components via
onBlur
,onChange
andonClick
handlers. You can pass the validation results to a flux (Redux?) store, making reducers and the store itself completely decoupled from the actual form validation logic.The version above does not have a concept of dependencies between different form fields but this could be achieved by e.g. a higher-level validation strategy pattern and extending
validateInput
to accept extra parameters containing validation rules that should be ignored or added.Brief description of the concepts and patterns in use
validationRuleToMethod
.inputTypeToValidations
).validateInput
function. This is a layer that might not be needed for simpler forms where all field names are unique and follow distinct validation rules.Implementation overview
You might want to implement this validation pattern inside of the form control event handlers. All you need to do is call
validateInput
and pass results of the call to Redux and get a reducer to store them against a particular field.Presentational React components then render any necessary validation messages as per the current Redux store state (see a screen grab example below).