Angular8中表单及其验证(基础应用篇)

2,035 阅读2分钟

一、前提

  1. 必要性:特别必要
  2. 意义:很有意义

二、正文

(一)、新建表单(模板表单)

  1. 新建名称为formValidator的ng项目——命令行输入ng new formValidator

  2. 修改pakage.json文件——添加参数,方便开发,命令行输入npm start启动项目;

"scripts": {
    "ng": "ng",
    "start": "ng serve --open --port 4210",//修改端口号&自动打开默认浏览器窗口
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  1. 新建组件,命令行输入ng g c templateForm --spec false

  2. 将app.components.html中的内容,替换成<app-template-form></app-template-form>

  3. app.module.ts中引入FormModul并在import中使用;

  4. 书写formValidator组件

    //template-form.html
    <div class="container">
      <form  (ngSubmit)="save()" #myForm="ngForm">
        <input 
          type="text" 
          [(ngModel)]="name" //双向数据绑定
          name="name" //使用form时必须定义,可以理解为当前控件的名字
          #myName="ngModel" //检查当前控件状态的出口,应用:myName.valid、myName.errors等
          autocomplete="off" //关闭浏览器自带的显示历史记录 h5新属性
          [appVerifyName]="nameList" //添加验证器
        >
        <!--invalid是否验证成功-->
        <!--dirty是否改变-->
        <!--touched是否被抚摸过-->
        <div *ngIf="myName.invalid && (myName.dirty || myName.touched)">
            <div *ngIf="myName.errors.required">
                名称为必填项
            </div>
            <div *ngIf="myName.errors.repeat">
                名称重复
            </div>  
        </div>
        <button type="submit" [disabled]="!myForm.form.valid">提交</button>  //验证通过才能提交  
      </form>
    </div>
    //template-form.ts
    ...
    
    name: string;
    
    nameAry:string[] = ['zhangsan','lisi','wangwu'];
    
    constructor() { }

    ngOnInit() {}
    
    save(): void{
        console.log('save 发请求')
    }
    ...

(二)、验证表单

  1. 新建指令,用于验证ng g c d share/verifyName
  2. 在share目录下新建nameValidator.ts,用于书写验证函数
   //share/nameValidator.ts
   
   import { ValidatorFn, AbstractControl } from "@angular/forms";

   export function nameValidator(nameList: string[]): ValidatorFn {
       return (control: AbstractControl): { [key: string]: any } | null => {
           //依据指令中传递进来的名称列表进行判断,如果包含,就返回一个对象,对象的key将
           //作为模板(template-form.html)中被验证的控件的erros的key,如果不包含返回null
           //表示验证通过
           return  nameList.includes(control.value) ? { 'repeat': { value: control.value } } : null;
       };
   }
  1. 书写指令——验证名称不能重复
   //verify-name.directive.ts
   
   import { Directive, Input } from '@angular/core';
   import { Validator, NG_VALIDATORS, AbstractControl } from '@angular/forms';
   import { nameValidator } from './nameValidator';
   
   @Directive({
     selector: '[appVerifyName]',
     providers: [{
       provide: NG_VALIDATORS,
       useExisting: VerifyNameDirective,
       multi: true
     }]
   })
   export class VerifyNameDirective implements Validator { //实现Validator接口
   
     @Input('appVerifyName') //接收验证规则(reg),或者你希望传到指令中的什么
     nameList: string[];
   
     validate(control: AbstractControl): { [key: string]: any } | null {
       return this.name ? nameValidator(nameList)(control) : null
     }
   }

三、碎碎念

如果只有一个表单或者项目比较小巧,用这样的验证机制,我认为是不太明智的(用ng都没必要),随便弄个计数器或者标识位就能达到dirty和touched的效果,反之,大概率上没有一个项目有一万个表单控件,定义9000个验证规则的,所以可以高度复用,而且维护起来也灵活一些

that's all