angular 模板驱动表单 表单检验(自定义校验器)

一 模板驱动表单

参考文献:angular官网-模板驱动表单

新建编辑页面

ng generate component hero/NameEditor

建出此表单 :

  1. 创建 Hero 模型类

  2. 创建控制此表单的组件。

  3. 创建具有初始表单布局的模板。

  4. 使用 ngModel 双向数据绑定语法把数据属性绑定到每个表单输入控件。

  5. 往每个表单输入控件上添加 name 属性 (attribute)。

  6. 显示和隐藏有效性验证的错误信息。

  7. 使用 ngSubmit 处理表单提交。

  8. 禁用此表单的提交按钮,直到表单变为有效

注意:一定要记得导入 FormsModule。模块哦!

name-editor.component.ts代码如下:

<div *ngIf="hero">
 <form (ngSubmit)="onSubmit(heroForm)" #heroForm="ngForm">
  姓名:<input type="text" [(ngModel)]="hero.name" name="name" #sname="ngModel" required/> <br/>
  <!--这里,创建了名叫 name 的变量,并且赋值为 "ngModel"。
  为什么是 “ngModel”? 指令的 exportAs 属性告诉 Angular 如何链接模板引用变量到指令。 
  这里把 name 设置为 ngModel 是因为 ngModel 指令的 exportAs 属性设置成了 “ngModel”。
  -->
  <div [hidden]="sname.valid || sname.pristine">*姓名为必填项</div>

  <div>
    性别: 
    <label><input type="radio" [(ngModel)]="hero.sex" name="sex" value="0"/>男</label>
    <label><input type="radio" [(ngModel)]="hero.sex" name="sex" value="1"/>女</label>
  </div>
  
  爱好:
  <select [(ngModel)]="hero.like" name="like" #like="ngModel" required>
    <option *ngFor="let l of likes" [value]="l.value">{{l.name}}</option>
  </select>
  <div [hidden]="like.valid || like.pristine">*爱好为必填项</div>

  <button type="submit" class="btn btn-success" [disabled]="!heroForm.form.valid">Submit</button>
  <button type="button" class="btn btn-default" (click)="heroForm.reset()">New Hero</button>

 </form>
</div>

 上面的代码解释:
1.一定要添加name=“attribute” 属性,否组会报错
2.#like="ngModel" , 创建了名叫 like的变量,并且赋值为 "ngModel"。
  为什么是 “ngModel”? 指令的 exportAs 属性告诉 Angular 如何链接模板引用变量到指令。 
  这里把 name 设置为 ngModel 是因为 ngModel 指令的 exportAs 属性设置成了 “ngModel”。
  因为是ngModel ,所以下面的like.valid和like.pristine会实时校验
 

name-editor.component.ts代码如下:

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
// import { Hero } from 'src/app/interfacer/hero';
// import { HEROS } from 'src/app/mock/Heros';

interface Like {
  value:string,
  name:string
}

class Hero {
  constructor(
    public id: number,
    public name: string,
    public sex: number | string, // 0:男,1:女
    public skill:string,
    public like?: string
  ) {  }
}

const HEROS:Hero[] = [
  new Hero(1,'貂蝉','1','法师','跳舞'),
  new Hero(2,'吕布','0','坦克','打架'),
  new Hero(3,'小乔','1','法术','跳舞'),
  new Hero(4,'周瑜','0','法师','打架'),
  new Hero(5,'李白','0','刺客','喝酒'),
  new Hero(6,'王昭君','1','法师','跳舞'),
  new Hero(7,'后羿','0','射手','射箭')
]

@Component({
  selector: 'app-name-editor',
  templateUrl: './name-editor.component.html',
  styleUrls: ['./name-editor.component.css']
})
export class NameEditorComponent implements OnInit {

  private hero:Hero;
  private likes:Like[] = [
    {value:'',name:'请选择'},
    {value:'打架',name:'打架'},
    {value:'射箭',name:'射箭'},
    {value:'喝酒',name:'喝酒'},
    {value:'跳舞',name:'跳舞'},
  ]
 
  constructor(private route:ActivatedRoute){}
  ngOnInit(){
    // 当前页面的路由为 http://localhost:4200/name-editor;id=7
    this.route.paramMap.subscribe(params => {
         this.hero = HEROS.filter(item => item.id === +params.get('id'))[0];
      }
    )
  }

  onSubmit() { console.log(this.hero) }

}

最后别忘了在app.module.ts里面declarations,以及app.routing.ts里面设置路径;

 二 模板驱动->表单校验(自定义校验器)

参考:自定义校验器

1.创建一个校验器,命名forbidden-name.directive.ts(记得在app.module.ts里面declarations),如下代码:

import { Directive, ElementRef, HostListener, Input } from '@angular/core';
import { Validator, AbstractControl, NG_VALIDATORS, ValidatorFn } from '@angular/forms';

// 校验的方法
// nameRe:传进来的正则
// control:当前需要校验的control元素,例如<input appForbiddenName="bob" .../> 
// 校验结果:如果传入的是bob则校验通不过
function forbiddenNameValidator(nameRe: RegExp): ValidatorFn {
    return (control: AbstractControl): {[key: string]: any} | null => {
      const forbidden = nameRe.test(control.value);
      return forbidden ? {'forbiddenName': {value: control.value}} : null;
    };
  }

@Directive({
  selector: '[appForbiddenName]',
  providers: [{provide: NG_VALIDATORS, useExisting: ForbiddenValidatorDirective, multi: true}]
})
export class ForbiddenValidatorDirective implements Validator {
    @Input('appForbiddenName') forbiddenName: string;
 
    validate(control: AbstractControl): {[key: string]: any} | null {
      // 如果有传入forbiddenName,就调用forbiddenNameValidator()方法校验,并返回校验结果,否则返回null
      return this.forbiddenName ? forbiddenNameValidator(new RegExp(this.forbiddenName, 'i'))(control)
                                : null;
    }
} //

2.使用:name-editor.component.ts

... 
姓名:<input type="text" [(ngModel)]="hero.name" name="name" #sname="ngModel" required  appForbiddenName="bob"/> <br/>

  <div *ngIf="name.errors?.forbiddenName">名字不可以为bob哦</div>
...
发布了112 篇原创文章 · 获赞 149 · 访问量 55万+

猜你喜欢

转载自blog.csdn.net/l284969634/article/details/102667901
今日推荐