Typescript Form Validation In React and React Framework Material UI
Multiple validations on TextFields or Select fields? Simply use this validation form coded in React, the framework Material UI and Typescript. It works with plain textfields and without the HTML form element.
You would like to implement your own validation, with your own error texts and Formic would be too over-engineered for your task? This simple React component implements this using custom hooks and tuned by the React framework Material UI.
With this simple React validation form, consisting of Material UI TextField
components (extendable with the select
prop to create a select component), several regex validations can be pipelined and the corresponding error messages can be displayed.
How the validation works
The React component works in such a way that the submit button is only active when no more errors exist inside the TextFields and possible required props are taken into account. If so, the component function submit
is called (in this example the input object will be just displayed).
function submit(){
let str = ALERT;
str += Object.keys(obj).map(item=>obj[item].value).join('\n');
alert(str);
}
Hence, own validations can be created and it is not necessary to resort to the HTML5 validation of the form
element (the form
HTML element is not used at all).
Material UI TextField
validated with React Custom Hook
Each input component inside the form uses the custom hook useFormValidation
for validation, which checks the input after each onChange
event and outputs the corresponding error message when necessary.
import React, { useState } from "react"
import { NO_ERROR, FIELD_REQUIRED } from '../constants'
type InitType = {
[key: string]: any
}
type FormValidationItemType = {
regex: RegExp,
errorMsg: string
}
type FormValidationType = {
[key: string]: {
value: string,
label: string,
required?: boolean,
valid: boolean,
validation: Array,
select?: Array
}
}
export const useFormValidation = (props: FormValidationType) => {
const {initValue, initValid, initHelperText} = getInitValues();
const [value, setValue] = useState(initValue);
const [isValid, setIsValid] = useState(initValid);
const [helperText, setHelperText] = useState(initHelperText);
function getInitValues(){
let initValue: InitType = {};
let initValid: InitType = {};
let initHelperText: InitType = {};
for (const [key, value] of Object.entries(props)) {
initValue[key] = value.value;
initValid[key] = value.valid;
initHelperText[key] = NO_ERROR;
}
return {initValue, initValid, initHelperText};
}
let obj: InitType = {};
for (const [key, val] of Object.entries(props)) {
obj[key] = {
value: value[key],
isValid: isValid[key],
required: val.required,
bind: {
value: value![key],
onChange: (event: React.ChangeEvent) => {
setValue(prev => {
return {...prev, [key]: event.target.value};
});
const required = event.target.required;
let validationArr = required ? [FIELD_REQUIRED]: [];
validationArr = validationArr.concat(val.validation);
let errArr = validationArr.map(v => {
return event.target.value.search(v.regex);
});
let validationState = errArr.filter(i => i < 0).length === 0 ? true : false;
let index = errArr.findIndex(e => e === -1 );
let errorMsg = validationState ? NO_ERROR : validationArr[index].errorMsg;
setHelperText(prev => {
return {...prev, [key]: errorMsg};
});
setIsValid(prev => {
return {...prev, [key]: validationState};
});
},
helperText: isValid[key] ? NO_ERROR : helperText![key],
error: !isValid[key],
},
}
}
obj.resetValue = () => {
const {initValue, initValid, initHelperText} = getInitValues();
setValue(initValue);
setIsValid(initValid);
setHelperText(initHelperText);
}
return obj;
}
If the required prop of the Material UI TextField
is set or true
, the individual validation is extended so that the TextField
is only valid if an input has been made.
This React validation component can be easily enhanced with further input components such as Radio buttons and Checkboxes.
Github Repository of the Code
CodePen Live-Demo