Angular5 Reactive Form
根据最近的使用,总结一下在ngx中使用reactive form
1. 创建表单
需求: 创建一个带验证的表单,如果表单验证不通过则提交按钮disabled=true
<!-- app.component.html --> <form [formGroup]="form"> <div class="form-group"> <label for="">name: </label> <input type="text" formControlName="name"> </div> <div class="form-group"> <label for="">password: </label> <input type="password" formControlName="password"> </div> <div class="form-group"> <button type="submit" (click)="submit()" [disabled]="form.invalid">submit</button> <button type="button" (click)="reset()">reset</button> </div> </form>
// app.component.ts import {Component,OnInit} from '@angular/core'; import {FormBuilder,FormControl,FormGroup,Validators} from '@angular/forms'; @Component({ selector: 'app-root',templateUrl: './app.component.html',styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit { name = 'app'; form: FormGroup; constructor( private fb: FormBuilder ){} ngOnInit(){ this.form = this.fb.group({ name: ['',Validators.required],password: ['',[Validators.required,Validators.minLength(6)]] }); } submit(){ if(this.form.valid){ console.log('submiting...') }else{ console.log('form is not valid') } } reset(){ this.form.reset(); } }
2. 自定义验证器
需求: 密码需要格式为数字字母下划线6-12位
// app.component.ts ... // 自定义密码验证 function ValidPwd(control: AbstractControl):any { const reg = /^\w{6,12}$/; if(reg.test(control.value)){ // 通过验证时需要返回 null return null; } return {status: 'error',message: '密码格式为数字字母下划线6-12位'} } ... export class AppComponent implements OnInit { ... ngOnInit(){ this.form = this.fb.group({ name: ['',ValidPwd]] }); } ... }
3. 动态创建表单
<!-- app.component.html --> <form [formGroup]="form"> <div class="form-group"> <label for="">name: </label> <input type="text" formControlName="name"> </div> <div class="form-group"> <label for="">password: </label> <input type="password" formControlName="password"> </div> <ng-container *ngFor="let friend of friends.controls; let i=index"> <div class="form-group"> <label for="">friend(s): </label> <input type="text" [formControl]="friend"> <span class="cursor-pointer hover-red" (click)="addFriend()" *ngIf="i===0">+</span> <span class="cursor-pointer hover-red" *ngIf="i!==0" (click)="removeFriend(i)">-</span> </div> </ng-container> <div class="form-group"> <button type="submit" (click)="submit()" [disabled]="form.invalid">submit</button> <button type="button" (click)="reset()">reset</button> </div> </form>
// app.component.ts ... export class AppComponent implements OnInit { name = 'app'; form: FormGroup; friends; constructor( private fb: FormBuilder ) {} ngOnInit() { this.form = this.fb.group({ name: ['',ValidPwd]],friends: this.fb.array([this.createFriend()]) }); this.friends = this.form.get('friends') as FormArray; } /** * 动态创建表单 * @returns {FormControl} */ createFriend() { return this.fb.control('',Validators.required); } /** * 增加输入框 */ addFriend(): void { this.friends.push(this.createFriend()); } /** * 移除输入框 * @param {number} i */ removeFriend(i: number): void { this.friends.removeAt(i); } ... }
4. standalone
需求: 增加单选框控制表单
在Reactive表单中,使用ngModel时,会出现报错
Error: ngModel cannot be used to register form controls with a parent formGroup directive.
报错中也提示了,应该在input中增加[ngModelOptions]="{standalone: true}"
standalone: Defaults to false. If this is set to true,thengModel
will not register itself with its parent form,and will act as if it's not in the form. This can be handy if you have form Meta-controls,a.k.a. form elements nested in the<form>
tag that control the display of the form,but don't contain form data.
现在表单变成这样:
<!-- app.component.html --> <form [formGroup]="form"> <div class="form-group"> <label for="">name: </label> <input type="text" formControlName="name"> </div> <div class="form-group"> <label for="">password: </label> <input type="password" formControlName="password"> </div> <ng-container *ngFor="let friend of friends.controls; let i=index"> <div class="form-group"> <label for="">friend(s): </label> <input type="text" [formControl]="friend"> <span class="cursor-pointer hover-red" (click)="addFriend()" *ngIf="i===0">+</span> <span class="cursor-pointer hover-red" *ngIf="i!==0" (click)="removeFriend(i)">-</span> </div> </ng-container> <div class="form-group"> <label for="">contactType: </label> mobile<input type="radio" value="0" [(ngModel)]="contactType" [ngModelOptions]="{standalone:true}">  landLine<input type="radio" value="1" [(ngModel)]="contactType" [ngModelOptions]="{standalone:true}"> </div> <div class="form-group"> <label for="">{{+contactType === 1?"landLine":"mobile"}}: </label> <input type="text" formControlName="contact"> </div> <div class="form-group"> <button type="submit" (click)="submit()" [disabled]="form.invalid">submit</button> <button type="button" (click)="reset()">reset</button> </div> </form>
app.componen.ts中增加contactType
变量,表单实例中增加contact
:
// app.component.ts ... export class AppComponent implements OnInit { name = 'app'; form: FormGroup; friends; contactType:number = 0; constructor( private fb: FormBuilder ) {} ngOnInit() { this.form = this.fb.group({ name: ['',friends: this.fb.array([this.createFriend()]),contact: ['',Validators.required] }); this.friends = this.form.get('friends') as FormArray; } /** * 动态创建表单 * @returns {FormControl} */ createFriend() { return this.fb.control('',Validators.required); } /** * 增加输入框 */ addFriend(): void { this.friends.push(this.createFriend()); } /** * 移除输入框 * @param {number} i */ removeFriend(i: number): void { this.friends.removeAt(i); } submit() { if (this.form.valid) { console.log('submitting...'); } else { console.log('form is not valid'); } } reset() { this.form.reset(); } }