Validator
Một cách để cải thiện chất lượng dữ liệu đầu vào bằng cách xác thực tính chính xác đầy đủ của dữ liệu
Trong bài viết lần này tôi sẽ giới thiệu đến các bạn 2 kiểu validate và hiển thị message bằng cách sử dụng reactive form và template-driven form trong Angular
Template-driven form
Là phương pháp tạo form bằng cách ghi lại logic, kiểm tra tính hợp lệ của dữ liệu trong template (html code) thông qua việc sử dụng cơ chế two-binding với cú pháp [ngModel]
Để thêm validation trong một template-driven form, bạn sẽ phải sử dụng những directive do Angular cung cấp hoặc custom để thêm vào trong mỗi input. Mỗi khi giá trị của form thay đổi, Angular sẽ chạy validation và sinh ra danh sách lỗi kèm theo status INVALID hoặc VALID
Xem ví dụ dưới đây
<input id="name" name="name" class="form-control" required minlength="4" appForbiddenName="name" [(ngModel)]="university.name" #name="ngModel" > <div *ngIf="name.invalid && (name.dirty || name.touched)" class="alert alert-danger"> <div *ngIf="name.errors.required"> // Kiểm tra lỗi đối với từng thuộc tính validation Name is required </div> <div *ngIf="name.errors.minlength"> Name must be at least 4 characters long. </div> <div *ngIf="name.errors.forbiddenName"> Name cannot be name </div> </div>
- Thẻ input mang một số thuộc tính HTML validation như required, minlength. Và cũng mang một directive để validate là forbiddenName
- #name=”ngModel” xuất NgModel trong một biến local “name”. NgModel phản ánh các thuộc tính dưới dạng FormControl nên bạn có thể sử dụng nó để kiểm tra trạng thái của các thuộc tính validation như touched, dirty, valid.
Nhược điểm :
- Dạng Template driven form dễ dàng để sử dụng, tuy nhiên việc sử dụng two-binding khi các thuộc tính validator ngày càng nhiều thì tốc độ đọc của form sẽ giảm xuống và khó để web designer có thể handle
- Logic validator của form không thể unit test được, cách kiểm tra duy nhất là khi chạy nó trên browser
=> Dạng validator form này thích hợp với những form đơn giản, không phù hợp với những form biến đổi hoặc cấu trúc form phức tạp
Reactive form validation
Là một phương pháp để tạo form trong Angular, phương pháp này tránh việc sử dụng các directive ví dụ như ngModel, required, etc, thay vào đó tạo các Object Model ở trong các Component, rồi tạo ra form từ chúng. Reactive form dùng phương pháp tiếp cận minh bạch rõ ràng và không đổi để quản lý state của form. Nghĩa là mỗi thay đổi trong form sẽ trả về một state mới, điều đó giúp duy trì tính toàn vẹn giữa các thay đổi. Với Reactive form bạn có thể truy cập đồng bộ tới các input trong form
Để giúp các bạn hiểu hơn, chúng ta hãy cùng xem qua một ví dụ tạo form login với reactive form
import { Component, OnInit, Input } from '@angular/core' import { Observable } from 'rxjs/Observable' import {FormControl, FormGroup, Validators} from '@angular/forms' @Component({ selector: 'app-signin', templateUrl: './signin.component.pug', styleUrls: ['./signin.component.styl'] }) export class SigninComponent implements OnInit { loginForm: FormGroup // Khởi tạo một FormGroup login (FormGroup sẽ chứa tất cả các FormControl trong form) constructor() { } ngOnInit() { this.loginForm = new FormGroup({ email: new FormControl('', [ //Mỗi formControl tương ứng với một input đầu vào Validators.required ]), // input Email sẽ bắt buộc phải required password: new FormControl('', [ Validators.required, Validators.minLength(6) // input Password sẽ bắt buộc phải có tối thiểu 6 kí tự nếu muốn form valid ]) }) } onSubmit(): void { if (this.loginForm.valid) { // kiểm tra FormGroup có thỏa mãn các điều kiện validation không } } checkValid(field: string) { return (this.loginForm.get(field).touched || this.submitted) } get password() { return this.loginForm.get('password') } get email() { return this.loginForm.get('email') } }
Sau đó phần html của component tương ứng sẽ gán biến loginForm
<form [formGroup]="loginForm"> // Khai báo biến loginForm <input [ngClass]="{'hasError': email.invalid && checkValid('email')}" name="email" formControlName="email" /> <div *ngIf="email.invalid && email.errors.required && checkValid('email')" class="error">This field is required</div> <input [ngClass]="{'hasError': password.invalid && checkValid('password')}" name="password" formControlName="password" /> <div *ngIf="password.invalid && password.errors.required && checkValid('password')" class="error">This field is required</div> <button type="submit" (click)="onSubmit()"></button> </form>
- formControlName=”email” tên tương ứng với key khai báo trong loginForm
- Lấy instance của thuộc tính trong formControl thông qua phương thức get. VD: this.loginForm.get(‘password’)
-
Bạn có thể add giá trị của form hiện tại thông qua tham số đầu tiên khi khởi tạo một FormControl
Ưu điểm:
- Bạn có thể kiểm tra logic validation một cách chính xác thông qua unit testing
- Có thể thay đổi một số giá trị của form như touched, dirty
- Mô hình No data binding được thực hiện làm tăng tốc độ đọc của form
- Code html trở nên ít hơn và thay vào đó nó được control trong component
=> Dễ dàng để tương tác với những form phức tạp hoặc những form thường xuyên có sự biến đổi
Qua bài viết này, bạn sẽ có cách nhìn đúng đắn hơn để cân nhắc việc sử dụng giữa hai dạng validation form này. Bài tiếp theo tôi sẽ giới thiệu tới các bạn kiến trúc store trong Angular
Tham khảo thêm tại: https://angular.io
Bạn có thể xem lại bài viết Tổng Quan về Angular tại đây: https://text.relipasoft.com/2018/11/tim-hieu-angular-5-phan-1/