Form Validation in ReactJS
Form validation is one of the most important parts of the software application. Today we will show you how to create form and validate it in ReactJS.
Form Validation in ReactJS, Simple form validation using react js, React js form validation example, React js form validation step by step for beginners. Example of form validation in React.
Checkout more articles on React JS:
In this article, We will create a simple form with the use of different type of the fields and apply validation on each fields. Also we will handle the validation on Submit button click as well.
Way to implement: Form Validation in ReactJS
- Setup react application
- Install dependencies
- Understanding of form fields and validation
- Create form design
- Manage form values in states
- Implement Validation in Form
- Output
1. Setup react application
First we have to setup the react application to create form validation demo in React JS. If you don’t know how to create react application then follow below link.
2. Install dependencies
We will add two major dependencies in react application
- Add bootstrap for designing
- Install react-select package for dropdown
1. Add bootstrap for designing
We will add bootstrap cdn css link in project for designing purpose only. For that, you have to add the following style link in public/index.html file.
1 | <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> |
public/index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <link rel="icon" href="%PUBLIC_URL%/favicon.ico" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="theme-color" content="#000000" /> <meta name="description" content="Web site created using create-react-app" /> <link rel="apple-touch-icon" href="logo192.png" /> <!-- manifest.json provides metadata used when your web app is installed on a user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/ --> <link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> <!-- Notice the use of %PUBLIC_URL% in the tags above. It will be replaced with the URL of the `public` folder during the build. Only files inside the `public` folder can be referenced from the HTML. Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will work correctly both with client-side routing and a non-root public URL. Learn how to configure a non-root public URL by running `npm run build`. --> <title>Form Validation in ReactJS - Clue Mediator</title> <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> </head> <body> <noscript>You need to enable JavaScript to run this app.</noscript> <div id="root"></div> <!-- This HTML file is a template. If you open it directly in the browser, you will see an empty page. You can add webfonts, meta tags, or analytics to this file. The build step will place the bundled scripts into the <body> tag. To begin the development, run `npm start` or `yarn start`. To create a production bundle, use `npm run build` or `yarn build`. --> </body> </html> |
2. Install react-select package for dropdown
In this demo, We will use react-select package to display dropdown. In order to use react-select you have to run below command to install package.
1 | npm i react-select |
3. Understanding of form fields and validations
In this demo will cover all the type of fields and implement validation for each field. We can also consider it as signup form. Checkout the below list for better understanding.
Field | HTML Element | Validations |
---|---|---|
Name | Input (type text) | required |
Input (type text) | required, email | |
Password | Input (type password) | required, compare it with Confirm Password field |
Confirm Password | Input (type password) | required, compare it with Password field |
Mobile | Input (type text) | required, number |
Gender | Input (type radio) | required |
Zip Code | Input (type text) | N/A |
Country | Dropdown (react-select) | required |
Language | Input (type checkbox) | required |
4. Create form design
Now we will create a simple design for signup page by the use of bootstrap classes. We will also display an asterisk (*) mark for mandatory fields and at last we will use “Submit” button to handle the form.
We have to define the two class variables to manage the list of Country and Language fields and those variable must be written in constructor or somewhere in static file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | constructor() { super(); this.countryList = [ { value: "india", label: "India" }, { value: "us", label: "US" }, { value: "australia", label: "Australia" } ]; this.languageList = [ { value: "english", label: "English" }, { value: "hindi", label: "Hindi" }, { value: "spanish", label: "Spanish" }, { value: "arabic", label: "Arabic" } ]; } |
Now your code should look like below.
App.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | import React, { Component } from 'react'; import ReactSelect from 'react-select'; class App extends Component { constructor() { super(); this.countryList = [ { value: "india", label: "India" }, { value: "us", label: "US" }, { value: "australia", label: "Australia" } ]; this.languageList = [ { value: "english", label: "English" }, { value: "hindi", label: "Hindi" }, { value: "spanish", label: "Spanish" }, { value: "arabic", label: "Arabic" } ]; } render() { return ( <div className="signup-box"> <p className="title">Sign up</p> <div className="row"> <div className="col-md-6"> <div className="form-group"> <label> Name:<span className="asterisk">*</span> </label> <input className="form-control" type="text" name="name" /> </div> <div className="form-group"> <label> Email:<span className="asterisk">*</span> </label> <input className="form-control" type="text" name="email" /> </div> <div className="form-group"> <label> Password:<span className="asterisk">*</span> </label> <input className="form-control" type="password" name="password" /> </div> <div className="form-group"> <label> Confirm Password:<span className="asterisk">*</span> </label> <input className="form-control" type="password" name="confirmPassword" /> </div> <div className="form-group"> <label className="mr-3"> Language:<span className="asterisk">*</span> </label> <div className="form-control border-0 p-0 pt-1"> {this.languageList.map((x, i) => { return ( <label key={i} className="mr-2"> <input type="checkbox" name="language" value={x.value} /> {x.label} </label> ); })} </div> </div> </div> <div className="col-md-6"> <div className="form-group"> <label> Mobile:<span className="asterisk">*</span> </label> <input className="form-control" type="text" name="mobile" /> </div> <div className="form-group"> <label className="mr-3"> Gender:<span className="asterisk">*</span> </label> <div className="form-control border-0 p-0 pt-1"> <label className="mr-2"> <input type="radio" name="gender" value="male" /> Male </label> <label> <input type="radio" name="gender" value="female" /> Female </label> </div> </div> <div className="form-group"> <label>Zip Code:</label> <input className="form-control" type="text" name="zipCode" /> </div> <div className="form-group"> <label> Country:<span className="asterisk">*</span> </label> <ReactSelect name="country" options={this.countryList} /> </div> </div> </div> <div className="form-group"> <input type="button" className="btn btn-primary" value="Submit" /> </div> </div> ); } } export default App; |
index.css
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | .signup-box{ border: 1px solid #ddd; width: 700px; margin: 20px auto; padding: 20px; border-radius: 5px; } .title{ font-weight: 600; margin-top:0; } .err { font-size: small; color: red; } .asterisk{ font-size: small; color: red; } |
5. Manage form values in states
Now we will create state variable to manage all fields of the form. For that create state variable as “form” to store the value of the form in the form of an object.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | constructor() { super(); this.state = { form: { name: "", email: "", mobile: "", password: "", confirmPassword: "", gender: null, language: [], country: null, zipCode: "" } }; this.countryList = [ { value: "india", label: "India" }, { value: "us", label: "US" }, { value: "australia", label: "Australia" } ]; this.languageList = [ { value: "english", label: "English" }, { value: "hindi", label: "Hindi" }, { value: "spanish", label: "Spanish" }, { value: "arabic", label: "Arabic" } ]; } |
We need one method where we can handle the change event of the html elements. It will be used to store the changed value in state variable. It should look like below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | handleChange = e => { const { name, value, checked } = e.target; const { form } = this.state; let formObj = {}; if (name === "language") { // handle the change event of language field if (checked) { // push selected value in list formObj = { ...form }; formObj[name].push(value); } else { // remove unchecked value from the list formObj = { ...form, [name]: form[name].filter(x => x !== value) }; } } else { // handle change event except language field formObj = { ...form, [name]: value }; } this.setState({ form: formObj }); } |
Now we will bind those variables with the HTML elements. We will bind two attributes (value & onChange) to make it working.
How to Handle Events in ReactJSYour render method should look like below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | render() { const { form } = this.state; return ( <div className="signup-box"> <p className="title">Sign up</p> <div className="row"> <div className="col-md-6"> <div className="form-group"> <label> Name:<span className="asterisk">*</span> </label> <input className="form-control" type="text" name="name" value={form.name} onChange={this.handleChange} /> </div> <div className="form-group"> <label> Email:<span className="asterisk">*</span> </label> <input className="form-control" type="text" name="email" value={form.email} onChange={this.handleChange} /> </div> <div className="form-group"> <label> Password:<span className="asterisk">*</span> </label> <input className="form-control" type="password" name="password" value={form.password} onChange={this.handleChange} /> </div> <div className="form-group"> <label> Confirm Password:<span className="asterisk">*</span> </label> <input className="form-control" type="password" name="confirmPassword" value={form.confirmPassword} onChange={this.handleChange} /> </div> <div className="form-group"> <label className="mr-3"> Language:<span className="asterisk">*</span> </label> <div className="form-control border-0 p-0 pt-1"> {this.languageList.map((x, i) => { return ( <label key={i} className="mr-2"> <input type="checkbox" name="language" value={x.value} checked={form.language.includes(x.value)} onChange={this.handleChange} /> {x.label} </label> ); })} </div> </div> </div> <div className="col-md-6"> <div className="form-group"> <label> Mobile:<span className="asterisk">*</span> </label> <input className="form-control" type="text" name="mobile" value={form.mobile} onChange={this.handleChange} /> </div> <div className="form-group"> <label className="mr-3"> Gender:<span className="asterisk">*</span> </label> <div className="form-control border-0 p-0 pt-1"> <label className="mr-2"> <input type="radio" name="gender" value="male" checked={form.gender === "male"} onChange={this.handleChange} /> Male </label> <label> <input type="radio" name="gender" value="female" checked={form.gender === "female"} onChange={this.handleChange} /> Female </label> </div> </div> <div className="form-group"> <label>Zip Code:</label> <input className="form-control" type="text" name="zipCode" value={form.zipCode} onChange={this.handleChange} /> </div> <div className="form-group"> <label> Country:<span className="asterisk">*</span> </label> <ReactSelect name="country" options={this.countryList} value={this.countryList.find(x => x.value == form.country)} onChange={e => this.handleChange({ target: { name: "country", value: e.value } }) } /> </div> </div> </div> <div className="form-group"> <input type="button" className="btn btn-primary" value="Submit" /> </div> </div> ); } |
Now we have to strict the number type for “Mobile” field. For that we have to validate the input field on key press event.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | validateNumber = evt => { var theEvent = evt || window.event; // Handle paste if (theEvent.type === "paste") { key = theEvent.clipboardData.getData("text/plain"); } else { // Handle key press var key = theEvent.keyCode || theEvent.which; key = String.fromCharCode(key); } var regex = /[0-9]|\./; if (!regex.test(key)) { theEvent.returnValue = false; if (theEvent.preventDefault) theEvent.preventDefault(); } }; . . . . . . . . . <div className="form-group"> <label> Mobile:<span className="asterisk">*</span> </label> <input className="form-control" type="text" name="mobile" value={form.mobile} onChange={this.handleChange} onKeyPress={this.validateNumber} /> </div> . . . . . . |
Now we have to handle the click event of the “Submit” button and write the console log of the form values.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | handleSubmit = () => { console.log(`Data: ${JSON.stringify(this.state.form)}`); }; . . . . . . <div className="form-group"> <input type="button" className="btn btn-primary" value="Submit" onClick={this.handleSubmit} /> </div> . . . . . . |
6. Implement Validation in Form
Now we will create function where we can validate the field based on the input value and return the validation message.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | validateField = (name, value, refValue) => { let errorMsg = null; switch (name) { case "name": if (!value) errorMsg = "Please enter Name."; break; case "email": if (!value) errorMsg = "Please enter Email."; else if (!/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@(([[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(value)) errorMsg = "Please enter valid Email."; break; case "mobile": if (!value) errorMsg = "Please enter Mobile."; break; case "country": if (!value) errorMsg = "Please select Country."; break; case "gender": if (!value) errorMsg = "Please select Gender."; break; case "password": // refValue is the value of Confirm Password field if (!value) errorMsg = "Please enter Password."; else if (refValue && value !== refValue) errorMsg = "Password and Confirm Password does not match."; break; case "confirmPassword": // refValue is the value of Password field if (!value) errorMsg = "Please enter Confirm Password."; else if (refValue && value !== refValue) errorMsg = "Password and Confirm Password does not match."; break; case "language": if (value.length === 0) errorMsg = "Please select Language."; break; default: break; } return errorMsg; }; |
Here we used refValue for Password and Confirm Password field to compare it with each other and based on it we are sending the appropriate message.
Below is the code where we define one more state variable as object to manage the error message.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | this.state = { form: { name: "", email: "", mobile: "", password: "", confirmPassword: "", gender: null, language: [], country: null, zipCode: "" }, formErrors: { name: null, email: null, mobile: null, password: null, confirmPassword: null, gender: null, language: null, country: null } }; |
Now we have to slightly change the “handleChange” method to validate the value after the setState. Checkout the updated method below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | handleChange = e => { const { name, value, checked } = e.target; const { form, formErrors } = this.state; let formObj = {}; if (name === "language") { // handle the change event of language field if (checked) { // push selected value in list formObj = { ...form }; formObj[name].push(value); } else { // remove unchecked value from the list formObj = { ...form, [name]: form[name].filter(x => x !== value) }; } } else { // handle change event except language field formObj = { ...form, [name]: value }; } this.setState({ form: formObj }, () => { if (!Object.keys(formErrors).includes(name)) return; let formErrorsObj = {}; if (name === "password" || name === "confirmPassword") { let refValue = this.state.form[ name === "password" ? "confirmPassword" : "password" ]; const errorMsg = this.validateField(name, value, refValue); formErrorsObj = { ...formErrors, [name]: errorMsg }; if (!errorMsg && refValue) { formErrorsObj.confirmPassword = null; formErrorsObj.password = null; } } else { const errorMsg = this.validateField( name, name === "language" ? this.state.form["language"] : value ); formErrorsObj = { ...formErrors, [name]: errorMsg }; } this.setState({ formErrors: formErrorsObj }); }); } |
To display the error message, We need to update render method same as below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | render() { const { form, formErrors } = this.state; return ( <div className="signup-box"> <p className="title">Sign up</p> <div className="row"> <div className="col-md-6"> <div className="form-group"> <label> Name:<span className="asterisk">*</span> </label> <input className="form-control" type="text" name="name" value={form.name} onChange={this.handleChange} onBlur={this.handleChange} /> {formErrors.name && <span className="err">{formErrors.name}</span>} </div> <div className="form-group"> <label> Email:<span className="asterisk">*</span> </label> <input className="form-control" type="text" name="email" value={form.email} onChange={this.handleChange} onBlur={this.handleChange} /> {formErrors.email && <span className="err">{formErrors.email}</span>} </div> <div className="form-group"> <label> Password:<span className="asterisk">*</span> </label> <input className="form-control" type="password" name="password" value={form.password} onChange={this.handleChange} onBlur={this.handleChange} /> {formErrors.password && <span className="err">{formErrors.password}</span>} </div> <div className="form-group"> <label> Confirm Password:<span className="asterisk">*</span> </label> <input className="form-control" type="password" name="confirmPassword" value={form.confirmPassword} onChange={this.handleChange} onBlur={this.handleChange} /> {formErrors.confirmPassword && <span className="err">{formErrors.confirmPassword}</span>} </div> <div className="form-group"> <label className="mr-3"> Language:<span className="asterisk">*</span> </label> <div className="form-control border-0 p-0 pt-1"> {this.languageList.map((x, i) => { return ( <label key={i} className="mr-2"> <input type="checkbox" name="language" value={x.value} checked={form.language.includes(x.value)} onChange={this.handleChange} /> {x.label} </label> ); })} </div> {formErrors.language && <span className="err">{formErrors.language}</span>} </div> </div> <div className="col-md-6"> <div className="form-group"> <label> Mobile:<span className="asterisk">*</span> </label> <input className="form-control" type="text" name="mobile" value={form.mobile} onChange={this.handleChange} onBlur={this.handleChange} onKeyPress={this.validateNumber} /> {formErrors.mobile && <span className="err">{formErrors.mobile}</span>} </div> <div className="form-group"> <label className="mr-3"> Gender:<span className="asterisk">*</span> </label> <div className="form-control border-0 p-0 pt-1"> <label className="mr-2"> <input type="radio" name="gender" value="male" checked={form.gender === "male"} onChange={this.handleChange} /> Male </label> <label> <input type="radio" name="gender" value="female" checked={form.gender === "female"} onChange={this.handleChange} /> Female </label> </div> {formErrors.gender && <span className="err">{formErrors.gender}</span>} </div> <div className="form-group"> <label>Zip Code:</label> <input className="form-control" type="text" name="zipCode" value={form.zipCode} onChange={this.handleChange} /> </div> <div className="form-group"> <label> Country:<span className="asterisk">*</span> </label> <ReactSelect name="country" options={this.countryList} value={this.countryList.find(x => x.value == form.country)} onChange={e => this.handleChange({ target: { name: "country", value: e.value } }) } /> {formErrors.country && <span className="err">{formErrors.country}</span>} </div> </div> </div> <div className="form-group"> <input type="button" className="btn btn-primary" value="Submit" onClick={this.handleSubmit} /> </div> </div> ); } |
Now at last we need to change the submit handler to validate the form before submitting it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | validateForm = (form, formErrors, validateFunc) => { const errorObj = {}; Object.keys(formErrors).map(x => { let refValue = null; if (x === "password" || x === "confirmPassword") { refValue = form[x === "password" ? "confirmPassword" : "password"]; } const msg = validateFunc(x, form[x], refValue); if (msg) errorObj[x] = msg; }); return errorObj; }; handleSubmit = () => { const { form, formErrors } = this.state; const errorObj = this.validateForm(form, formErrors, this.validateField); if (Object.keys(errorObj).length != 0) { this.setState({ formErrors: { ...formErrors, ...errorObj } }); return false; } console.log('Data: ', form); }; |
That’s it for form validation.
7. Output
After following each step your whole code of file should look like below.
App.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 | import React, { Component } from 'react'; import ReactSelect from 'react-select'; class App extends Component { constructor() { super(); this.state = { form: { name: "", email: "", mobile: "", password: "", confirmPassword: "", gender: null, language: [], country: null, zipCode: "" }, formErrors: { name: null, email: null, mobile: null, password: null, confirmPassword: null, gender: null, language: null, country: null } }; this.countryList = [ { value: "india", label: "India" }, { value: "us", label: "US" }, { value: "australia", label: "Australia" } ]; this.languageList = [ { value: "english", label: "English" }, { value: "hindi", label: "Hindi" }, { value: "spanish", label: "Spanish" }, { value: "arabic", label: "Arabic" } ]; } validateNumber = evt => { var theEvent = evt || window.event; // Handle paste if (theEvent.type === "paste") { key = theEvent.clipboardData.getData("text/plain"); } else { // Handle key press var key = theEvent.keyCode || theEvent.which; key = String.fromCharCode(key); } var regex = /[0-9]|\./; if (!regex.test(key)) { theEvent.returnValue = false; if (theEvent.preventDefault) theEvent.preventDefault(); } }; handleChange = e => { const { name, value, checked } = e.target; const { form, formErrors } = this.state; let formObj = {}; if (name === "language") { // handle the change event of language field if (checked) { // push selected value in list formObj = { ...form }; formObj[name].push(value); } else { // remove unchecked value from the list formObj = { ...form, [name]: form[name].filter(x => x !== value) }; } } else { // handle change event except language field formObj = { ...form, [name]: value }; } this.setState({ form: formObj }, () => { if (!Object.keys(formErrors).includes(name)) return; let formErrorsObj = {}; if (name === "password" || name === "confirmPassword") { let refValue = this.state.form[ name === "password" ? "confirmPassword" : "password" ]; const errorMsg = this.validateField(name, value, refValue); formErrorsObj = { ...formErrors, [name]: errorMsg }; if (!errorMsg && refValue) { formErrorsObj.confirmPassword = null; formErrorsObj.password = null; } } else { const errorMsg = this.validateField( name, name === "language" ? this.state.form["language"] : value ); formErrorsObj = { ...formErrors, [name]: errorMsg }; } this.setState({ formErrors: formErrorsObj }); }); } validateField = (name, value, refValue) => { let errorMsg = null; switch (name) { case "name": if (!value) errorMsg = "Please enter Name."; break; case "email": if (!value) errorMsg = "Please enter Email."; else if (!/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@(([[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(value)) errorMsg = "Please enter valid Email."; break; case "mobile": if (!value) errorMsg = "Please enter Mobile."; break; case "country": if (!value) errorMsg = "Please select Country."; break; case "gender": if (!value) errorMsg = "Please select Gender."; break; case "password": // refValue is the value of Confirm Password field if (!value) errorMsg = "Please enter Password."; else if (refValue && value !== refValue) errorMsg = "Password and Confirm Password does not match."; break; case "confirmPassword": // refValue is the value of Password field if (!value) errorMsg = "Please enter Confirm Password."; else if (refValue && value !== refValue) errorMsg = "Password and Confirm Password does not match."; break; case "language": if (value.length === 0) errorMsg = "Please select Language."; break; default: break; } return errorMsg; }; validateForm = (form, formErrors, validateFunc) => { const errorObj = {}; Object.keys(formErrors).map(x => { let refValue = null; if (x === "password" || x === "confirmPassword") { refValue = form[x === "password" ? "confirmPassword" : "password"]; } const msg = validateFunc(x, form[x], refValue); if (msg) errorObj[x] = msg; }); return errorObj; }; handleSubmit = () => { const { form, formErrors } = this.state; const errorObj = this.validateForm(form, formErrors, this.validateField); if (Object.keys(errorObj).length !== 0) { this.setState({ formErrors: { ...formErrors, ...errorObj } }); return false; } console.log('Data: ', form); }; render() { const { form, formErrors } = this.state; return ( <div className="signup-box"> <p className="title">Sign up</p> <div className="row"> <div className="col-md-6"> <div className="form-group"> <label> Name:<span className="asterisk">*</span> </label> <input className="form-control" type="text" name="name" value={form.name} onChange={this.handleChange} onBlur={this.handleChange} /> {formErrors.name && <span className="err">{formErrors.name}</span>} </div> <div className="form-group"> <label> Email:<span className="asterisk">*</span> </label> <input className="form-control" type="text" name="email" value={form.email} onChange={this.handleChange} onBlur={this.handleChange} /> {formErrors.email && <span className="err">{formErrors.email}</span>} </div> <div className="form-group"> <label> Password:<span className="asterisk">*</span> </label> <input className="form-control" type="password" name="password" value={form.password} onChange={this.handleChange} onBlur={this.handleChange} /> {formErrors.password && <span className="err">{formErrors.password}</span>} </div> <div className="form-group"> <label> Confirm Password:<span className="asterisk">*</span> </label> <input className="form-control" type="password" name="confirmPassword" value={form.confirmPassword} onChange={this.handleChange} onBlur={this.handleChange} /> {formErrors.confirmPassword && <span className="err">{formErrors.confirmPassword}</span>} </div> <div className="form-group"> <label className="mr-3"> Language:<span className="asterisk">*</span> </label> <div className="form-control border-0 p-0 pt-1"> {this.languageList.map((x, i) => { return ( <label key={i} className="mr-2"> <input type="checkbox" name="language" value={x.value} checked={form.language.includes(x.value)} onChange={this.handleChange} /> {x.label} </label> ); })} </div> {formErrors.language && <span className="err">{formErrors.language}</span>} </div> </div> <div className="col-md-6"> <div className="form-group"> <label> Mobile:<span className="asterisk">*</span> </label> <input className="form-control" type="text" name="mobile" value={form.mobile} onChange={this.handleChange} onBlur={this.handleChange} onKeyPress={this.validateNumber} /> {formErrors.mobile && <span className="err">{formErrors.mobile}</span>} </div> <div className="form-group"> <label className="mr-3"> Gender:<span className="asterisk">*</span> </label> <div className="form-control border-0 p-0 pt-1"> <label className="mr-2"> <input type="radio" name="gender" value="male" checked={form.gender === "male"} onChange={this.handleChange} /> Male </label> <label> <input type="radio" name="gender" value="female" checked={form.gender === "female"} onChange={this.handleChange} /> Female </label> </div> {formErrors.gender && <span className="err">{formErrors.gender}</span>} </div> <div className="form-group"> <label>Zip Code:</label> <input className="form-control" type="text" name="zipCode" value={form.zipCode} onChange={this.handleChange} /> </div> <div className="form-group"> <label> Country:<span className="asterisk">*</span> </label> <ReactSelect name="country" options={this.countryList} value={this.countryList.find(x => x.value === form.country)} onChange={e => this.handleChange({ target: { name: "country", value: e.value } }) } /> {formErrors.country && <span className="err">{formErrors.country}</span>} </div> </div> </div> <div className="form-group"> <input type="button" className="btn btn-primary" value="Submit" onClick={this.handleSubmit} /> </div> </div> ); } } export default App; |
Please tell me this is not how you usually do form validation. It’s a mess
This is for the demo example but in the actual project, we have to create a reusable component for each type of the field such as input, button, radio/checkbox button list, textarea, etc.