Form Validation trong ứng dụng NativeScript Angular
Bài đăng này đã không được cập nhật trong 7 năm
Ở bài viết trước, tôi đã tạo một ứng dụng demo để giới thiệu về NativeScript. Trong bài này, chúng ta sẽ đi sâu vào cách xây dựng ứng dụng NativeScript, cụ thể là sử dụng Angular để xác thực dữ liệu phía client. Mặc dù NativeScript có hỗ trợ Angular, sẽ có một số khác biệt nhỏ giữa cách triển khai ứng dụng trên web với trên mobile bởi vì NativeScript sử dụng các tùy chỉnh XML so với tiêu chuẩn HTML trên web.
Tải về source code đầy đủ tại đây .
Tạo project NativeScript với Angular
Mục đích của hướng dẫn là xác minh tính hợp lệ của dữ liệu đầu vào trên form input require như ví dụ dưới đây:
Mặc định là bạn đã cài đặt NativeScript CLI và cấu hình đầy đủ. Trên CLI, chạy lệnh sau:
tns create ns-validation-project --ng
Flag --ng
xác định xây dựng một ứng dụng Angular
chứ không phải ứng dụng NativeScript
thuần.
Cần dọn dẹp một chút trước khi tiếp tục vì ứng dụng NativeScript Angular
mẫu tạo ra nhiều thứ không cần thiết.
Mở app/app.routing.ts
và xóa mảng routes
. Ứng dụng trang đơn của chúng ta không cần định tuyến nào. Tệp sau khi dọn dẹp giống thế này:
import { NgModule } from "@angular/core";
import { NativeScriptRouterModule } from "nativescript-angular/router";
import { Routes } from "@angular/router";
const routes: Routes = [];
@NgModule({
imports: [NativeScriptRouterModule.forRoot(routes)],
exports: [NativeScriptRouterModule]
})
export class AppRoutingModule { }
Các component
và service
cũng cần bỏ khỏi app/app.module.ts
:
import { NgModule, NO_ERRORS_SCHEMA } from "@angular/core";
import { NativeScriptModule } from "nativescript-angular/nativescript.module";
import { NativeScriptFormsModule } from "nativescript-angular/forms";
import { AppRoutingModule } from "./app.routing";
import { AppComponent } from "./app.component";
@NgModule({
bootstrap: [
AppComponent
],
imports: [
NativeScriptModule,
AppRoutingModule,
NativeScriptFormsModule
],
declarations: [
AppComponent
],
providers: [],
schemas: [
NO_ERRORS_SCHEMA
]
})
export class AppModule { }
Bắt đầu được rồi, mặc dù không nhất thiết phải sửa đổi những file trên, nhưng tôi thích sự gọn gàng và để tránh nhầm lẫn.
Sử dụng Angular Validators
Angular
, giống như AngularJS
, có một bộ các validator
. Những validator này dùng được trong cả web và NativeScript.
Ví dụ với field email
. Field này có các trạng thái dirty
, pristine
, touched
, valid
và invalid
. Trạng thái là dirty
khi đã được sử dụng và ngược lại là pristine
nếu chưa được sử dụng, touched
khi trường bị blur
. Nếu thỏa mãn tất cả các quy tắc, trạng thái là valid
và ngược lại là invalid
.
Mở app/app.component.html
thêm vào HTML sau:
<ActionBar title="{N} Form Validation"></ActionBar>
<StackLayout class="form">
<StackLayout class="input-field">
<Label text="Email" class="label font-weight-bold m-b-5"></Label>
<TextField #email="ngModel" [(ngModel)]="input.email" class="input" required></TextField>
<StackLayout class="hr-light"></StackLayout>
</StackLayout>
<StackLayout class="input-field">
<Label text="Password" class="label font-weight-bold m-b-5"></Label>
<TextField #password="ngModel" secure="true" [(ngModel)]="input.password" class="input" required></TextField>
<StackLayout class="hr-light"></StackLayout>
</StackLayout>
<StackLayout class="input-field">
<StackLayout *ngIf="email.errors && (email.dirty || email.touched)">
<Label *ngIf="email.errors.required" text="- An email is required -"></Label>
</StackLayout>
<StackLayout *ngIf="password.errors && (password.dirty || password.touched)">
<Label *ngIf="password.errors.required" text="- A password is required -"></Label>
</StackLayout>
</StackLayout>
<StackLayout class="input-field">
<Button *ngIf="email.valid && password.valid" text="Login" class="btn btn-primary"></Button>
</StackLayout>
</StackLayout>
Giao diện gồm hai field
(email
, password
) và một button
(login
). Các field là bắt buộc nhập (require
). Nếu field đã được sử dụng hoặc bị mờ, sẽ hiển thị lỗi và ẩn nút login. Nếu validate ok, hiện nút và không hiển thị lỗi.
Điều này được thực hiện thông qua ngModel
trên mỗi TextField
. Ví dụ #email="ngModel"
và #password="ngModel"
. Để các biến này hoạt động, phải có một ràng buộc hai chiều sử dụng thuộc tính [(ngModel)]
.
Xây dựng Directive xác thực
Nhiều khi những validator cơ bản không đáp ứng được yêu cầu của bạn, ví dụ khi bạn muốn đặt độ dài tối thiểu cho TextField
, khi đó cần phải tự xây dựng một validator riêng. Ngoài ra bạn có thể thêm bất cứ luật nào mà bạn nghĩ ra
Tạo file app/input.directive.ts
giống như sau:
import { Directive, Input } from '@angular/core';
import { NG_VALIDATORS, Validator, AbstractControl } from '@angular/forms';
@Directive({
selector: '[minlength]',
providers: [{provide: NG_VALIDATORS, useExisting: MinLengthDirective, multi: true}]
})
export class MinLengthDirective implements Validator {
@Input() minlength: string;
public constructor() {}
public validate(control: AbstractControl): {[key: string]: any} {
return !control.value || control.value.length >= this.minlength ? null : { "minlength": true };
}
}
@Directive({
selector: '[email]',
providers: [{provide: NG_VALIDATORS, useExisting: IsEmailDirective, multi: true}]
})
export class IsEmailDirective implements Validator {
public constructor() {}
public validate(control: AbstractControl): {[key: string]: any} {
let emailRegEx = /^(([^<>()\[\]\\.,;:\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,}))$/i;
let valid = emailRegEx.test(control.value);
return control.value < 1 || valid ? null : {'email': true};
}
}
Bắt đầu với MinLengthDirective
:
@Directive({
selector: '[minlength]',
providers: [{provide: NG_VALIDATORS, useExisting: MinLengthDirective, multi: true}]
})
export class MinLengthDirective implements Validator {
@Input() minlength: string;
public constructor() {}
public validate(control: AbstractControl): {[key: string]: any} {
return !control.value || control.value.length >= this.minlength ? null : { "minlength": true };
}
}
Bằng cách thêm một @Input()
trùng tên, nếu một giá trị trên form dài hơn chiều dài được xác định sẽ trả về null
. Giá trị null
chỉ ra rằng nội dung là hợp lệ. Nếu không, sẽ trả ra bất kì đối tượng nào và xử lý nó.
Điều này đưa chúng ta đến IsEmailDirective
, dùng xác nhận biểu thức chính quy:
@Directive({
selector: '[email]',
providers: [{provide: NG_VALIDATORS, useExisting: IsEmailDirective, multi: true}]
})
export class IsEmailDirective implements Validator {
public constructor() {}
public validate(control: AbstractControl): {[key: string]: any} {
let emailRegEx = /^(([^<>()\[\]\\.,;:\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,}))$/i;
let valid = emailRegEx.test(control.value);
return control.value < 1 || valid ? null : {'email': true};
}
}
Sử dụng Email RegEx để kiểm tra xem giá trị đầu vào có hợp lệ hay không.
Trước khi sử dụng, cần thêm các Directive
này vào @NgModule
. Mở app/app.module.ts
thêm các Directive
và các mảng declarations
:
import { NgModule, NO_ERRORS_SCHEMA } from "@angular/core";
import { NativeScriptModule } from "nativescript-angular/nativescript.module";
import { NativeScriptFormsModule } from "nativescript-angular/forms";
import { AppRoutingModule } from "./app.routing";
import { AppComponent } from "./app.component";
import { MinLengthDirective, IsEmailDirective } from "./input.directive";
@NgModule({
bootstrap: [
AppComponent
],
imports: [
NativeScriptModule,
AppRoutingModule,
NativeScriptFormsModule
],
declarations: [
AppComponent,
MinLengthDirective,
IsEmailDirective
],
providers: [],
schemas: [
NO_ERRORS_SCHEMA
]
})
export class AppModule { }
Vậy là đủ. Sửa app/app.component.html
như sau:
<ActionBar title="{N} Form Validation"></ActionBar>
<StackLayout class="form">
<StackLayout class="input-field">
<Label text="Email" class="label font-weight-bold m-b-5"></Label>
<TextField #email="ngModel" [(ngModel)]="input.email" class="input" required email></TextField>
<StackLayout class="hr-light"></StackLayout>
</StackLayout>
<StackLayout class="input-field">
<Label text="Password" class="label font-weight-bold m-b-5"></Label>
<TextField #password="ngModel" secure="true" minlength="5" [(ngModel)]="input.password" class="input" required></TextField>
<StackLayout class="hr-light"></StackLayout>
</StackLayout>
<StackLayout class="input-field">
<StackLayout *ngIf="email.errors && (email.dirty || email.touched)">
<Label *ngIf="email.errors.required" text="- An email is required -"></Label>
<Label *ngIf="email.errors.email" text="- Email must be valid -"></Label>
</StackLayout>
<StackLayout *ngIf="password.errors && (password.dirty || password.touched)">
<Label *ngIf="password.errors.required" text="- A password is required -"></Label>
<Label *ngIf="password.errors.minlength" text="- Password must be longer than 5 characters"></Label>
</StackLayout>
</StackLayout>
<StackLayout class="input-field">
<Button *ngIf="email.valid && password.valid" text="Login" class="btn btn-primary"></Button>
</StackLayout>
</StackLayout>
Có những thay đổi nào?
Trong TextField
cho email
, thêm một thuộc tính email
. Tương ứng với Directive đã định nghĩa. Nó không có giá trị vì chỉ muốn xác nhận dữ liệu thường. Trong khối lỗi, cũng chỉ kiểm tra các lỗi xác nhận hợp lệ liên quan đến email.
Trong TextField
cho password
, thêm thuộc tính minlength
chứa một giá trị số. Hãy nhớ rằng, giá trị đó là những gì chúng ta đang kiểm tra bên trong Directive
. Tôi cũng thêm in lỗi cho Directive
này.
Kết luận
Bạn đã biết cách để thêm form validate cho một ứng dụng NativeScript Angular
chưa?. Đơn giản nó là những gì đã có sẵn trong Angular
thông qua Angular Directive
. Validating form giúp trải nghiệm người dùng thêm tinh tế. Tuy nhiên, không nên dùng nó thay cho việc xác thực phía Backend
.
Nguồn: developer.telerik.com
All rights reserved