当前位置: 首页 > news >正文

Angular4 模板式表单用法以及验证

NgForm指令

在表单中声明一个模板变量,往<form>标签中加入#heroForm="ngForm",代码如下:

<form #heroForm="ngForm">

heroForm变量是一个到NgForm指令的引用,它代表该表单的整体。

  • 什么是NgForm指令? 但我们明明没有添加过NgForm指令啊!
  • Angular替你做了。Angular会在<form>标签上自动创建并附加一个NgForm指令。
  • NgForm指令为form增补了一些额外特性。 它会控制那些带有ngModel指令和name属性的元素,监听他们的属性(包括其有效性)。 它还有自己的valid属性,这个属性只有在它包含的每个控件都有效时才是真。

注意,当在表单中使用[(ngModel)]时,必须要定义name属性。在内部,Angular 创建了一些FormControl,并把它们注册到NgForm指令,再将该指令附加到<form>标签。 注册每个FormControl时,使用name属性值作为键值

通过 ngModel 跟踪修改状态与有效性验证

状态为真时的 CSS 类为假时的 CSS 类
控件被访问过ng-touchedng-untouched
控件的值变化了ng-dirtyng-pristine
控件的值有效ng-validng-invalid

往姓名<input>标签上添加名叫 spy 的临时模板引用变量, 然后用这个 spy 来显示它上面的所有 CSS 类:

<input type="text" class="form-control" id="name"
  required
  [(ngModel)]="model.name" name="name"
  #spy>
<br>TODO: remove this: {{spy.className}}

添加用于视觉反馈的自定义 CSS:

.ng-valid[required], .ng-valid.required  {
  border-left: 5px solid #42A948; /* green */
}

.ng-invalid:not(form)  {
  border-left: 5px solid #a94442; /* red */
}

模板引用变量可以访问模板中输入框的 Angular 控件。 这里,创建了名叫name的变量,并且赋值为 "ngModel",用来显示和隐藏验证错误信息:

<label for="name">Name</label>
<input type="text" class="form-control" id="name"
       required
       [(ngModel)]="model.name" name="name"
       #name="ngModel">
<div [hidden]="name.valid || name.pristine"
     class="alert alert-danger">
  Name is required
</div>

为什么是 “ngModel”? 指令的 exportAs 属性告诉 Angular 如何链接模板引用变量到指令。 这里把name设置为ngModel是因为ngModel指令的exportAs属性设置成了 “ngModel”。

使用 ngSubmit 提交该表单

<form (ngSubmit)="onSubmit()" #heroForm="ngForm">
    ------------------------
    <button type="submit" class="btn btn-success" [disabled]="!heroForm.form.valid">Submit</button>
</form>

模板驱动验证

为了往模板驱动表单中添加验证机制,我们要添加一些验证属性,就像原生的HTML表单验证器。 Angular 会用指令来匹配这些具有验证功能的指令。

  • 每当表单控件中的值发生变化时,Angular 就会进行验证,并生成一个验证错误的列表(对应着INVALID状态)或者null(对应着VALID状态)。
  • 我们可以通过把ngModel导出成局部模板变量来查看该控件的状态。 比如下面这个例子就把NgModel导出成了一个名叫name的变量:
<form novalidate>
  <input id="name" name="name" class="form-control"
         required minlength="4" forbiddenName="bob"
         [(ngModel)]="hero.name" #name="ngModel" >
  <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.forbiddenName">
      Name cannot be Bob.
    </div>
  </div>
</form>

请注意以下几点:

  • <input>元素带有一些HTML验证属性:required 和 minlength。它还带有一个自定义的验证器指令forbiddenName
  • name="ngModel"把NgModel导出成了一个名叫name的局部变量。NgModel把自己控制的FormControl实例的属性映射出去,让我们能在模板中检查控件的状态,比如valid和dirty
  • <div>元素的*ngIf揭露了一套嵌套消息divs,但是只在有“name”错误和控制器为dirty或者touched
  • 每个嵌套的<div>为其中一个可能出现的验证错误显示一条自定义消息。比如 required、minlength和 forbiddenName

自定义验证器

  • 在模板驱动表单中,我们不用直接访问FormControl实例。所以我们不能像响应式表单中那样把验证器传进去,而应该在模板中添加一个指令
  • Angular在验证流程中的识别出指令的作用,是因为指令把自己注册到了NG_VALIDATORS提供商中,该提供商拥有一组可扩展的验证器
forbidden-name.directive.ts (providers)

providers: [{provide: NG_VALIDATORS, useExisting: ForbiddenValidatorDirective, multi: true}]

然后该指令类实现了Validator接口,以便它能简单的与 Angular 表单集成在一起:

@Directive({
  selector: '[appForbiddenName]',
  providers: [{provide: NG_VALIDATORS, useExisting: ForbiddenValidatorDirective, multi: true}]
})
export class ForbiddenValidatorDirective implements Validator {
  @Input() forbiddenName: string;
 
  validate(control: AbstractControl): {[key: string]: any} {
    return this.forbiddenName ? forbiddenNameValidator(new RegExp(this.forbiddenName, 'i'))(control)
                              : null;
  }
}

forbiddenNameValidator函数,该函数的定义看起来是这样的:

export function forbiddenNameValidator(nameRe: RegExp): ValidatorFn {
  return (control: AbstractControl): {[key: string]: any} => {
    const forbidden = nameRe.test(control.value);
    return forbidden ? {'forbiddenName': {value: control.value}} : null;
  };
}

一旦 ForbiddenValidatorDirective写好了,我们只要把forbiddenName选择器添加到输入框上就可以激活这个验证器了。比如:

<input id="name" name="name" class="form-control"
       required minlength="4" forbiddenName="bob"
       [(ngModel)]="hero.name" #name="ngModel" >

你可能注意到了自定义验证器指令是用useExisting而不是useClass来实例化的。注册的验证器必须是这个 ForbiddenValidatorDirective 实例本身,也就是表单中 forbiddenName 属性被绑定到了"bob"的那个。如果用useClass来代替useExisting,就会注册一个新的类实例,而它是没有forbiddenName的。

相关文章:

  • vsftpd服务器安装(只限下载)
  • 通过实例模拟ASP.NET MVC的Model绑定机制:简单类型+复杂类型
  • 快照和文件备份以及文件系统的恢复
  • 三本关于机器学习和深度学习的书
  • DataGridView使用初步
  • 链式前向星
  • 只在UnitTest和WebHost中的出现的关于LogicalCallContext的严重问题
  • SQL Server 2008使用LINQ进行数据访问(转载自IT168 [ http://www.it168.com/ ])
  • Windows中运行Python的两种运行方式
  • GNS3使用详解2
  • 数据类型测试及转换案例
  • VS2010编译Web项目要用 batch=false
  • 《WCF技术剖析》博文系列汇总[持续更新中]
  • 在linux中怎样用命令完全拷贝一个目录下的所有文件(包括隐藏文件以及文件夹)到另外一个目录下...
  • 传输层TCP
  • CSS居中完全指南——构建CSS居中决策树
  • java多线程
  • MyEclipse 8.0 GA 搭建 Struts2 + Spring2 + Hibernate3 (测试)
  • 当SetTimeout遇到了字符串
  • 短视频宝贝=慢?阿里巴巴工程师这样秒开短视频
  • 服务器之间,相同帐号,实现免密钥登录
  • 高程读书笔记 第六章 面向对象程序设计
  • 理解IaaS, PaaS, SaaS等云模型 (Cloud Models)
  • 提升用户体验的利器——使用Vue-Occupy实现占位效果
  • 项目实战-Api的解决方案
  • 云大使推广中的常见热门问题
  • 400多位云计算专家和开发者,加入了同一个组织 ...
  • AI算硅基生命吗,为什么?
  • #162 (Div. 2)
  • #Linux(帮助手册)
  • #绘制圆心_R语言——绘制一个诚意满满的圆 祝你2021圆圆满满
  • $ is not function   和JQUERY 命名 冲突的解说 Jquer问题 (
  • (3)(3.2) MAVLink2数据包签名(安全)
  • (4)STL算法之比较
  • (MATLAB)第五章-矩阵运算
  • (PHP)设置修改 Apache 文件根目录 (Document Root)(转帖)
  • (Redis使用系列) Springboot 实现Redis消息的订阅与分布 四
  • (附源码)springboot猪场管理系统 毕业设计 160901
  • (机器学习-深度学习快速入门)第一章第一节:Python环境和数据分析
  • (转)IIS6 ASP 0251超过响应缓冲区限制错误的解决方法
  • (转)从零实现3D图像引擎:(8)参数化直线与3D平面函数库
  • (转)如何上传第三方jar包至Maven私服让maven项目可以使用第三方jar包
  • 、写入Shellcode到注册表上线
  • .java 9 找不到符号_java找不到符号
  • .Net 6.0 处理跨域的方式
  • .NET 简介:跨平台、开源、高性能的开发平台
  • .NET基础篇——反射的奥妙
  • .NET开源的一个小而快并且功能强大的 Windows 动态桌面软件 - DreamScene2
  • .NET企业级应用架构设计系列之结尾篇
  • @RestController注解的使用
  • @TableLogic注解说明,以及对增删改查的影响
  • @value 静态变量_Python彻底搞懂:变量、对象、赋值、引用、拷贝
  • @vue/cli 3.x+引入jQuery
  • [ 隧道技术 ] cpolar 工具详解之将内网端口映射到公网
  • [.net] 如何在mail的加入正文显示图片