利用angular4和nodejs-express构建一个简单的网站(七)—用户注册之ReactiveForm
这一节对用户注册组件进行分析。
用户注册组件主要涉及angular4表单的操作。Angular提供了两种构建表单的技术:响应式表单和模板驱动表单。 这两项技术都属于@angular/forms库,并且共享一组公共的表单控件类。我在用户注册组件(regist.component)中使用的是响应式表单(ReactiveFormsModule),要了解更多angular表单的知识,可以访问官方文档,里面介绍的很详细。
注册组件模板分析
用户注册需要用户名、密码、邮箱(非必须)三个信息注册表单组件的模板代码如下:
<form [formGroup]="registForm" (ngSubmit)="onSubmit()" novalidate>
<div class="form-group">
<label for="name">User name</label>
<input class="form-control" formControlName="name" id="name" required>
<div *ngIf="name.invalid && (name.dirty || name.touched)" class="alert alert-danger">
<div *ngIf="name.errors.required">
Name is required!
</div>
<div *ngIf="name.errors.minlength">
Name must be at least 4 characters long.
</div>
<div *ngIf="name.errors.pattern">
Name must be composed of letters, numbers
</div>
</div>
</div>
<div class="form-group">
<label for="password">Password</label>
<input class="form-control" formControlName="password" type="password" required id="password" #pass>
<div *ngIf="password.invalid && (password.dirty || password.touched)" class="alert alert-danger">
<div *ngIf="password.errors.required">
Password is required!
</div>
<div *ngIf="password.errors.minlength">
Password must be at least 8 characters long.
</div>
<div *ngIf="password.errors.pattern">
<!--密码必须由字母、数字、下划线和减号组成,首字母要求大写 -->
Password must be composed of letters, numbers, '_', '-' and Capital letters must be capitalized.
</div>
</div>
</div>
<div class="from-group">
<label for="repassword">Re Password</label>
<input type="password" class="form-control" required id="repassword" (focus)="checkValid()"
formControlName="repassword">
<div class="alert alert-danger" *ngIf="repassword.invalid && (repassword.dirty || repassword.touched)">
<div *ngIf="repassword.errors.required">
Re password is required!
</div>
<div *ngIf="repassword.errors.comparePassword">
Re password must equal password!
</div>
</div>
</div>
<div class="form-group email-group">
<label for="email">Email</label>
<input class="form-control" formControlName="email" type="email" id="email">
<div *ngIf="email.invalid &&(email.dirty || email.touched)" class="alert alert-danger">
<div *ngIf="email.errors.pattern">
The email address format is incorrect
</div>
</div>
</div>
<div class="form-group form-btn">
<button type="submit" class="btn btn-primary" [disabled]="registForm.invalid">Submit</button>
<button type="button" class="btn btn-light" [disabled]="registForm.pristine" (click)="revert()">Cancel</button>
</div>
</form>
导航到regist组件后在name、password、repassword、email中添加相应的信息,点击Submit按钮,就会触发ngSubmit事件,在form标签中定义处理ngSubmit事件的函数onSubmit(),onSubmit()函数将注册信息发送到服务器。
novalidate阻止浏览器使用原生HTML表单验证,因为这里使用了angular的表单验证。
对于响应式表单需要在模板的form标签中声明formGroup(在这里formGroup声明为registForm),还需要在输入控件(如input、select等)标签中声明formControlName。
模板中还有一些关于表单验证的内容,如下面的代码:
<div *ngIf="password.invalid && (password.dirty || password.touched)" class="alert alert-danger">
...
</div>
在表单状态为dirty(脏)状态和touched(碰过)状态时如果password为invalid(不合法,表单控件不合法(invalid)表示未能满足控件的验证规则),div标识符中的内容将呈现到password控件的下方。违反了不同的验证规则,会呈现不同的内容,如在上一段代码中的div标签中还包裹着:
<div *ngIf="password.errors.required">
Password is required!
</div>
表明在违反了“password.errors.required”规则时,会呈现“Password is required!”内容。
在提交按钮(Submit)上的标记[disabled]="registForm.invalid",表示当form表单有不符合验证规则的输入时,按钮不能使用。
取消输入按钮(Cancel)在控件值未发生变化时(registForm.pristine)不能使用。
模板的基本分析就到这里,下面我们来看看ts文件中的组件类。
注册组件组件类分析
注册组件的组件类设计内容较多,在这里分部进行分析。
首先要创建响应式表单并定义表单的认证规则。需要从forms模块中引入FormBuilder、 FormGroup和Validators类。
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
并在构造方法中声明并初始化这三个类。
constructor(
...
private fb: FormBuilder,
private userSer: UserService,
private tokenServ: AuthTokenService) {
...
}
下一步利用FormBuilder创建表单。创建一个方法createForm(),用于创建表单,方法中的代码如下:
this.registForm = this.fb.group({
'name': [this.user.name, [
Validators.required,
Validators.minLength(4),
Validators.pattern(/^[a-z]|[A-Z]|[0-9]$/)]],
'password': [this.user.password,
[Validators.required,
Validators.minLength(8),
Validators.pattern(/^[A-Z][a-zA-Z0-9_-]+$/)]],
'email': [this.user.email,
Validators.pattern(/^([a-zA-Z0-9_\.\-]+)@([a-zA-Z0-9_\.\-]+)\.([a-zA-Z]{2,4})$/)],
'repassword': [this.user.password, [
Validators.required]]
});
registForm是一个FormGroup的实例,关联模板中的formGroup([formGroup]="registForm"),在类中进行声明:
registForm: FormGroup;
利用FormBuilder.group来生成响应式表单,FormBuilder.group是一个用来创建FormGroup的工厂方法,它接受一个对象,对象的键和值分别是FormControl的名字和它的定义。在这个对象中对name、password、email、repassword四个FormControl进行了初始化。定义了这四个FormControl的初始值对应User类的对象user的四个同名属性(repassword对应的是user.password,用于对用户密码的重复输入进行验证)。user对象也是在类中定义的:
user: User = new User(0, '', '', '');
表单验证
在FormControl的初始化中还定义了验证规则,这个表单的验证规则由以下几种:
- 必须输入内容(Validators.required)
- 最少需要x个字符(Validators.minlength(x))
- 正则验证,必须由字母、数字组成
Validators.pattern(/^[a-z]|[A-Z]|[0-9]$/) - 正则验证,必须由字母、数字、下划线和减号组成,首字母要求大写
Validators.pattern(/^[A-Z][a-zA-Z0-9_-]+$/)]] - 必须符合email格式要求,可以使用Validators.email,也可以使用正则验证。
对FormControl进行验证,还需要编写get方法来访问表单控件:
get name() { return this.registForm.get('name'); }
get password() { return this.registForm.get('password'); }
get email() { return this.registForm.get('email'); }
get repassword() { return this.registForm.get('repassword'); }
这里还需要自定义一个验证器,用于验证repassword输入的值是否和password的值相同。
自定义验证器由一个验证工厂函数构成。代码如下:
import { AbstractControl,ValidatorFn } from '@angular/forms';
export function passwordEquals(password: string): ValidatorFn {
return (control: AbstractControl): { [key: string]: any } => {
const isEquals = (password === control.value);
return isEquals ? null : { 'comparePassword': control.value };
}
}
passwordEquals()方法需要传入一个string类型的参数,返回配置好的验证器函数。该函数接受一个Angular控制器对象,在控制器的值和参数相同时返回null,不相同时返回验证错误对象,错误对象是一个现实控件值的键值对。
将自定义验证器加到表单的repassword属性上,但因为passwordEquals()的参数需要的是password控件的值,而password控件的值不能在表单创建时拿到,需要在password控件有值后才能拿到。那么,进行自定义验证器加载的最好时机就是repassword控件获得焦点的时候。所以,在模板中要加入repassword控件的标签中加入焦点事件:(focus)="checkValid()",在处理焦点事件的checkValid()函数中,为repassword加入自定义验证规则,判断它的值是否和控件password的值相同:
checkValid() {
this.repassword.setValidators([Validators.required, passwordEquals(this.pass.nativeElement.value)]);
}
this.pass是通过在password的<input>组件中声明一个引用变量#pass后,通过@ViewChild('pass') pass: ElementRef;获取到password的<input>组件的值。
关于用户注册中响应式表单(ReactiveForm)的构建和验证基本上就是这些了,下一章将要介绍如何向服务器发送注册信息并导航到下一个模块。
关于angular表单验证规则和验证方法可以查看官方文档中的介绍。
利用angular4和nodejs-express构建一个简单的网站(七)—用户注册之ReactiveForm的更多相关文章
- 利用angular4和nodejs-express构建一个简单的网站(五)—用户的注册和登录-HttpClient
上一节简单介绍了一下利用angular构建的主路由模块,根据上一节的介绍,主页面加载时直接跳转到用户管理界面,下面就来介绍一下用户管理模块.启动应用后,初始界面应该是这样的: 用户管理模块(users ...
- 利用angular4和nodejs-express构建一个简单的网站(一)——构建前后端开发环境
学习了一段时间的angular4知识,结合以前自学的nodejs-express后端框架知识,做了一个利用angular4作为前端,node-express作为后端服务器的网站.这个网站的功能很简单, ...
- 利用angular4和nodejs-express构建一个简单的网站(十)—好友模块
上一章讲解了用户登录的相关代码.用户登录成功后,就会进入好友模块,在好友模块中会根据不同的用户ID显示相应的好友列表,点击好友列表中的单个好友就会进入编辑单个好友页面,对好友信息进行编辑.点击列表页面 ...
- nodejs+express创建一个简单的服务器
//首先安装express //1.引入express const express = require('express'); //2.创建服务器对象 let server = express(); ...
- 利用HTML5与jQuery技术创建一个简单的自动表单完成
来源:GBin1.com 在线演示 在线下载 谷歌快速搜索自带大量自动完成插件——库中甚至还有一个附带的jQuery UI共享选项.然而今天我要寻找一个替代的解决方案.由DevBridge开发的j ...
- 构建一个简单的基于MVC模式的JavaWeb
零晨三点半了,刚刚几个兄弟一起出去吼歌,才回来,这应该是我大学第二次去K歌,第一次是大一吧,之后每次兄弟喊我,我都不想去,因为我还是很害怕去KTV,或许是因为那里是我伤心的地方,也或许是因为我在那里失 ...
- 通过python 构建一个简单的聊天服务器
构建一个 Python 聊天服务器 一个简单的聊天服务器 现在您已经了解了 Python 中基本的网络 API:接下来可以在一个简单的应用程序中应用这些知识了.在本节中,将构建一个简单的聊天服务器.使 ...
- struts1:(Struts重构)构建一个简单的基于MVC模式的JavaWeb
在构建一个简单的基于MVC模式的JavaWeb 中,我们使用了JSP+Servlet+JavaBean构建了一个基于MVC模式的简单登录系统,但在其小结中已经指出,这种模式下的Controller 和 ...
- 【Android Developers Training】 3. 构建一个简单UI
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
随机推荐
- python面试_总结03_列表练习题
1.列表练习题 完成下列列表相关的编程题,先运行下列的test函数,在完成每道题之后,都可以通过调用test函数检测所写函数对错. def test(got, expected): if got == ...
- 论文翻译:2020_DCCRN: Deep Complex Convolution Recurrent Network for Phase-Aware Speech Enhancement
论文地址:DCCRN:用于相位感知语音增强的深度复杂卷积循环网络 论文代码:https://paperswithcode.com/paper/dccrn-deep-complex-convolutio ...
- JSP 表单提交 数据库乱码解决方法
问题:有时候在做jsp逻辑处理时,比如提交表单,从前台注册的页面提交了一部分的数据,但是后面处理的JSP页面通过 request.getParameter 调用时,获取到的是一堆乱码. 乱码分析:因为 ...
- 6. 堪比JMeter的.Net压测工具 - Crank 实战篇 - 收集诊断跟踪信息与如何分析瓶颈
目录 堪比JMeter的.Net压测工具 - Crank 入门篇 堪比JMeter的.Net压测工具 - Crank 进阶篇 - 认识yml 堪比JMeter的.Net压测工具 - Crank 进阶篇 ...
- 在数据结构与算法中 传值方式(C语言)
传值方式 前言 当初学顺序链表的时候,书上就出现了这样的语言,如下所示: Status InitList_Sq(SqList &L) { //构造一个空的线性表L. L.elem = (Ele ...
- 神经网络中的Heloo,World,基于MINST数据集的LeNet
前言 最近刚开始接触机器学习,记录下目前的一些理解,以及看到的一些好文章mark一下 1.MINST数据集 MNIST 数据集来自美国国家标准与技术研究所, National Institute of ...
- 前面顺序表的补充(复杂度,未实现的算法,空间扩展)(基于c语言)
0.对于顺序表中的n个元素,如果在下标i的位置之前插入一个元素,则需要将后面n-i个元素向后移动一位:如果是删除下标为i处的元素,则是则需要将后面n-i-1个元素向前移动一位.如果说在i的位置插入和删 ...
- 4月17日 python学习总结 反射、object内置方法、元类
一.反射 下述四个函数是专门用来操作类与对象属性的,如何操作? 通过字符串来操作类与对象的属性,这种操作称为反射 class People: country="China" def ...
- Blazor 001 : 一个激进的Web开发框架
本文从比较高的位置俯瞰一下 .NET Blazor 技术方向,主要是给大家介绍一下"什么是 Blazor" 文章后半部分会给出一个 Blazor 中的 Hello World 示例 ...
- linux命令管道工作原理与使用方法
一.管道定义 管道是一种两个进程间进行单向通信的机制.因为管道传递数据的单向性,管道又称为半双工管道.管道的这一特点决定了器使用的局限性.管道是Linux支持的最初Unix IPC形式之一,具有以下特 ...