一 模板驱动表单
参考文献:angular官网-模板驱动表单
新建编辑页面
ng generate component hero/NameEditor
建出此表单 :
-
创建
Hero
模型类 -
创建控制此表单的组件。
-
创建具有初始表单布局的模板。
-
使用
ngModel
双向数据绑定语法把数据属性绑定到每个表单输入控件。 -
往每个表单输入控件上添加
name
属性 (attribute)。 -
显示和隐藏有效性验证的错误信息。
-
使用 ngSubmit 处理表单提交。
-
禁用此表单的提交按钮,直到表单变为有效
注意:一定要记得导入 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>
...