- vừa được xem lúc

ReactJs - Viết một Validator class đơn giản dùng để validate form

0 0 34

Người đăng: Nguyễn Thịnh Hưng

Theo Viblo Asia

Trước kia khi validate form bên phía client side mình thưởng sử dụng plugin jquery-validation, tuyên nhiên khi làm việc với ReactJs, dự liệu form thược được chứa trong state, vì vậy sử dụng jquery-validation không còn hợp lý nữa, việc sử dụng jQuery trong code ReactJs cũng không phải là một cách làm hay. Trong bài viết này mình sẽ hướng dẫn các bạn viết một class dùng để validate form trong ReactJs có thể sử dụng lại cho nhiều trường hợp.

Cài đặt

Chúng ta sẽ sử dụng create-react-app để tạo ứng dụng ReactJs.

Cài đặt package sử dụng npm:

npm install -g create-react-app

Tạo ứng dụng:

create-react-app react-form-validation-sample

Chạy ứng dụng:

cd react-form-validation-sample/
yarn start

Truy cập vào http://localhost:3000/ trên trình duyệt bạn sẽ thấy ứng dụng đã có thể chạy được:

Chuẩn bị

Mình kiếm được một form snippet khá đẹp trên codepen, nên mình sẽ fork về và sử dụng nó trong ứng dụng này:

Style

Sửa file src/App.css :

body { margin: auto; background: #eaeaea; font-family: 'Open Sans', sans-serif;
} .info p { text-align:center; color: #999; text-transform:none; font-weight:600; font-size:15px; margin-top:2px
} .info i { color:#F6AA93;
}
form h1 { font-size: 18px; background: #F6AA93 none repeat scroll 0% 0%; color: rgb(255, 255, 255); padding: 22px 25px; border-radius: 5px 5px 0px 0px; margin: auto; text-shadow: none; text-align:left
} form { border-radius: 5px; max-width:700px; width:100%; margin: 5% auto; background-color: #FFFFFF; overflow: hidden;
} p span { color: #F00;
} p { margin: 0px; font-weight: 500; line-height: 2; color:#333;
} h1 { text-align:center; color: #666; text-shadow: 1px 1px 0px #FFF; margin:50px 0px 0px 0px
} input { border-radius: 0px 5px 5px 0px; border: 1px solid #eee; margin-bottom: 15px; width: 75%; height: 40px; float: left; padding: 0px 15px;
} a { text-decoration:inherit
} textarea { border-radius: 0px 5px 5px 0px; border: 1px solid #EEE; margin: 0; width: 75%; height: 130px; float: left; padding: 0px 15px;
} .form-group { overflow: hidden; clear: both;
} .icon-case { width: 35px; float: left; border-radius: 5px 0px 0px 5px; background:#eeeeee; height:42px; position: relative; text-align: center; line-height:40px;
} i { color:#555;
} .contentform { padding: 40px 30px;
} .bouton-contact{ background-color: #81BDA4; color: #FFF; text-align: center; width: 100%; border:0; padding: 17px 25px; border-radius: 0px 0px 5px 5px; cursor: pointer; margin-top: 40px; font-size: 18px;
} .leftcontact { width:49.5%; float:left; border-right: 1px dotted #CCC; box-sizing: border-box; padding: 0px 15px 0px 0px;
} .rightcontact { width:49.5%; float:right; box-sizing: border-box; padding: 0px 0px 0px 15px;
} .validation { display:none; margin: 0 0 10px; font-weight:400; font-size:13px; color: #DE5959;
} #sendmessage { border:1px solid #fff; display:none; text-align:center; margin:10px 0; font-weight:600; margin-bottom:30px; background-color: #EBF6E0; color: #5F9025; border: 1px solid #B3DC82; padding: 13px 40px 13px 18px; border-radius: 3px; box-shadow: 0px 1px 1px 0px rgba(0, 0, 0, 0.03);
} #sendmessage.show,.show { display:block;
} 

Tạo form

File src/App.js gồm những field đơn giản như name, email, address, subject và message, handle event change lưu data vào state.

import React, { Component } from 'react';
import './App.css'; class App extends Component { constructor (props) { super(props); this.state = { name: '', email: '', address: '', subject: '', message: '', }; } handleInput = (e) => { this.setState({ [e.target.name]: e.target.value, }); }; handleSubmit = (e) => { // Handle validation here }; render() { return ( <div className="App"> <link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet" /> <h1>Elegant Contact Form.</h1> <form> <h1>Should you have any questions, please do not hesitate to contact me :</h1> <div className="contentform"> <div id="sendmessage"> Your message has been sent successfully. Thank you. </div> <div className="leftcontact"> <div className="form-group"> <p>Name <span>*</span></p> <span className="icon-case"><i className="fa fa-user"></i></span> <input type="text" name="name" value={this.state.name} onChange={this.handleInput}/> <div className="validation"></div> </div> <div className="form-group"> <p>E-mail <span>*</span></p> <span className="icon-case"><i className="fa fa-envelope-o"></i></span> <input type="email" name="email" value={this.state.email} onChange={this.handleInput}/> <div className="validation"></div> </div> <div className="form-group"> <p>Address <span>*</span></p> <span className="icon-case"><i className="fa fa-location-arrow"></i></span> <input type="text" name="address" value={this.state.address} onChange={this.handleInput}/> <div className="validation"></div> </div> </div> <div className="rightcontact"> <div className="form-group"> <p>Subject <span>*</span></p> <span className="icon-case"><i className="fa fa-comment-o"></i></span> <input type="text" name="subject" value={this.state.subject} onChange={this.handleInput}/> <div className="validation"></div> </div> <div className="form-group"> <p>Message <span>*</span></p> <span className="icon-case"><i className="fa fa-comments-o"></i></span> <textarea name="message" onChange={this.handleInput}>{this.state.message}</textarea> <div className="validation"></div> </div> </div> </div> <button type="button" className="bouton-contact">Send</button> </form> </div> ); }
} export default App;

Đây là kết quả sau khi đã custom form trên ReactJs:

Validator class

Cài đặt package validator:

npm install --save validator

Validator class

Nội dung file src/utils/validator.js:

import methods from 'validator'; class Validator { constructor(rules) { this.rules = rules; this.initiate(); } initiate() { this.isValid = true; this.errors = {}; } validate(state) { this.initiate(); this.rules.forEach((rule) => { if (this.errors[rule.field]) return; const fieldValue = state[rule.field] || ''; const args = rule.args || []; const validationMethod = typeof rule.method === 'string' ? methods[rule.method] : rule.method; if (validationMethod(fieldValue, ...args, state) !== rule.validWhen) { this.errors[rule.field] = rule.message; this.isValid = false; } }); return this.errors; }
} export default Validator;

Constructor truyền vào mảng rules

const requiredWith = (value, field, state) => state[field] && value;
const rules = [ { field: 'name', method: 'isEmpty', validWhen: false, message: 'The name field is required.', }, { field: 'name', method: 'isLength', args: [{min: 5}], validWhen: true, message: 'The name must be at least 5 characters.', }, { field: 'message', method: requiredWith, args: ['subject'], validWhen: true, message: 'The message field is required when subject is present.', }, ];

Mỗi rule sẽ bao gồm:

  • field : key của field trong state
  • method: method dùng để validate, nếu method là string sẽ lấy các methods trong package validator. Ngoài ra có thể tự viết method như ở trên mình viết có viếtrequiredMethod có các tham số truyền vào là value, các tham số khác, sau đó là state. requiredMethod sẽ check xem nếu field truyền vào và value có giá trị sẽ trả về true.
  • args: các tham số sẽ truyền vào.
  • validWhen: true hay false thì sẽ valid
  • message: message khi có lỗi

Initiate function

Khởi tạo các giá trị của validator

Validate function

Duyệt lần lượt các rules và chạy method của nó, nếu có lỗi sẽ add vào errors object một property với key là key của field, value là message báo lỗi. VD:

{ name: 'The name field is required.', email: 'The email must be a valid email address.'
}

App.js

Import validator

import Validator from './utils/validator';

Thêm state errors:

 this.state = { errors: {}, };

Khởi tạo validator trong constructor:

 const requiredWith = (value, field, state) => (!state[field] && !value) || !!value; const rules = [ { field: 'name', method: 'isEmpty', validWhen: false, message: 'The name field is required.', }, { field: 'name', method: 'isLength', args: [{min: 5}], validWhen: true, message: 'The name must be at least 5 characters.', }, { field: 'email', method: 'isEmpty', validWhen: false, message: 'The email field is required.', }, { field: 'email', method: 'isEmail', validWhen: true, message: 'The email must be a valid email address.', }, { field: 'address', method: 'isEmpty', validWhen: false, message: 'The address field is required.', }, { field: 'message', method: requiredWith, args: ['subject'], validWhen: true, message: 'The message field is required when subject is present.', }, ]; this.validator = new Validator(rules);

Thêm code validate trong method handleSubmit:

 handleSubmit = (e) => { this.setState({ errors: this.validator.validate(this.state), }); };

Hiển thị lỗi trong method render:

{errors.name && <div className="validation" style={{display: 'block'}}>{errors.name}</div>}

File App.js đầy đủ sẽ như sau:

import React, { Component } from 'react';
import Validator from './utils/validator';
import './App.css'; class App extends Component { constructor (props) { super(props); this.state = { name: '', email: '', address: '', subject: '', message: '', errors: {}, }; const requiredWith = (value, field, state) => (!state[field] && !value) || !!value; const rules = [ { field: 'name', method: 'isEmpty', validWhen: false, message: 'The name field is required.', }, { field: 'name', method: 'isLength', args: [{min: 5}], validWhen: true, message: 'The name must be at least 5 characters.', }, { field: 'email', method: 'isEmpty', validWhen: false, message: 'The email field is required.', }, { field: 'email', method: 'isEmail', validWhen: true, message: 'The email must be a valid email address.', }, { field: 'address', method: 'isEmpty', validWhen: false, message: 'The address field is required.', }, { field: 'message', method: requiredWith, args: ['subject'], validWhen: true, message: 'The message field is required when subject is present.', }, ]; this.validator = new Validator(rules); } handleInput = (e) => { this.setState({ [e.target.name]: e.target.value, }); }; handleSubmit = (e) => { this.setState({ errors: this.validator.validate(this.state), }); console.log(this.state); }; render() { const {errors} = this.state; return ( <div className="App"> <link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet" /> <h1>Elegant Contact Form.</h1> <form> <h1>Should you have any questions, please do not hesitate to contact me :</h1> <div className="contentform"> <div id="sendmessage"> Your message has been sent successfully. Thank you. </div> <div className="leftcontact"> <div className="form-group"> <p>Name <span>*</span></p> <span className="icon-case"><i className="fa fa-user"></i></span> <input type="text" name="name" value={this.state.name} onChange={this.handleInput}/> {errors.name && <div className="validation" style={{display: 'block'}}>{errors.name}</div>} </div> <div className="form-group"> <p>E-mail <span>*</span></p> <span className="icon-case"><i className="fa fa-envelope-o"></i></span> <input type="email" name="email" value={this.state.email} onChange={this.handleInput}/> {errors.email && <div className="validation" style={{display: 'block'}}>{errors.email}</div>} </div> <div className="form-group"> <p>Address <span>*</span></p> <span className="icon-case"><i className="fa fa-location-arrow"></i></span> <input type="text" name="address" value={this.state.address} onChange={this.handleInput}/> {errors.address && <div className="validation" style={{display: 'block'}}>{errors.address}</div>} </div> </div> <div className="rightcontact"> <div className="form-group"> <p>Subject</p> <span className="icon-case"><i className="fa fa-comment-o"></i></span> <input type="text" name="subject" value={this.state.subject} onChange={this.handleInput}/> {errors.subject && <div className="validation" style={{display: 'block'}}>{errors.subject}</div>} </div> <div className="form-group"> <p>Message</p> <span className="icon-case"><i className="fa fa-comments-o"></i></span> <textarea name="message" value={this.state.message} onChange={this.handleInput}/> {errors.message && <div className="validation" style={{display: 'block'}}>{errors.message}</div>} </div> </div> </div> <button type="button" className="bouton-contact" onClick={this.handleSubmit}>Send</button> </form> </div> ); }
} export default App;

Kết quả

Source code

https://github.com/thinhhung/react-form-validation-sample

Bình luận

Bài viết tương tự

- vừa được xem lúc

Giới thiệu Typescript - Sự khác nhau giữa Typescript và Javascript

Typescript là gì. TypeScript là một ngôn ngữ giúp cung cấp quy mô lớn hơn so với JavaScript.

0 0 500

- vừa được xem lúc

Cài đặt WSL / WSL2 trên Windows 10 để code như trên Ubuntu

Sau vài ba năm mình chuyển qua code trên Ubuntu thì thật không thể phủ nhận rằng mình đã yêu em nó. Cá nhân mình sử dụng Ubuntu để code web thì thật là tuyệt vời.

0 0 374

- vừa được xem lúc

Đặt tên commit message sao cho "tình nghĩa anh em chắc chắn bền lâu"????

. Lời mở đầu. .

1 1 701

- vừa được xem lúc

Tìm hiểu về Resource Controller trong Laravel

Giới thiệu. Trong laravel, việc sử dụng các route post, get, group để gọi đến 1 action của Controller đã là quá quen đối với các bạn sử dụng framework này.

0 0 335

- vừa được xem lúc

Phân quyền đơn giản với package Laravel permission

Như các bạn đã biết, phân quyền trong một ứng dụng là một phần không thể thiếu trong việc phát triển phần mềm, dù đó là ứng dụng web hay là mobile. Vậy nên, hôm nay mình sẽ giới thiệu một package có thể giúp các bạn phân quyền nhanh và đơn giản trong một website được viết bằng PHP với framework là L

0 0 421

- vừa được xem lúc

Bạn đã biết các tips này khi làm việc với chuỗi trong JavaScript chưa ?

Hi xin chào các bạn, tiếp tục chuỗi chủ đề về cái thằng JavaScript này, hôm nay mình sẽ giới thiệu cho các bạn một số thủ thuật hay ho khi làm việc với chuỗi trong JavaScript có thể bạn đã hoặc chưa từng dùng. Cụ thể như nào thì hãy cùng mình tìm hiểu trong bài viết này nhé (go).

0 0 414