一 模板驱动表单
参考文献:angular官网-模板驱动表单
新建编辑页面
ng generate component hero/NameEditor
建出此表单 :
创建Hero
模型类
创建控制此表单的组件。
创建具有初始表单布局的模板。
使用ngModel
双向数据绑定语法把数据属性绑定到每个表单输入控件。
往每个表单输入控件上添加name
属性 (attribute)。
显示和隐藏有效性验证的错误信息。
使用ngSubmit处理表单提交。
禁用此表单的提交按钮,直到表单变为有效
注意:一定要记得导入FormsModule
。模块哦!
name-ponent.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-ponent.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-ponent.html',styleUrls: ['./name-ponent.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=7this.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()方法校验,并返回校验结果,否则返回nullreturn this.forbiddenName ? forbiddenNameValidator(new RegExp(this.forbiddenName, 'i'))(control): null;}} //
2.使用:name-ponent.ts
... 姓名:<input type="text" [(ngModel)]="hero.name" name="name" #sname="ngModel" required appForbiddenName="bob"/> <br/><div *ngIf="name.errors?.forbiddenName">名字不可以为bob哦</div>...