angular4 Form表单相关

ng4中,有两种方式去声明一个表单

一:Template-Driven Forms - 模板驱动式表单 [引入FormsModule]

1.ngForm赋值 [可以方便的获取表单的]

<form #f='ngForm' novalidate (ngSumbit)='onSubmit(f)'>
  <input type='text'
         name='username'
         [(ngModel)]='login.username'
         required>
  <div *ngIf='f.controls.username?.required' class='error'>
    Name is required. 
 </div> 
</form>  
   

2.ngModel绑定 [ngModel会自动关联表单控件name属性,并使用该值作为ngForm对象的属性名]

以下有三种写法:

<input type='text' name='username' ngModel>
<input type='text' name='username' [ngModel]='login.username'>
<input type='text' name='username' [(ngModel)]='login.username'>

3.ngModel赋值 [可以操纵表单控件的事件]

<form #f='ngForm' novalidate (ngSumbit)='onSubmit(f)'>
  <input type='text'
          name='username'
          [(ngModel)]='login.username'
          #username='ngModel'
          (change)='changeName(username.value)'
          required>
  <div *ngIf='username.error?.required && username.touched' class='error'>
    Name is required. 
 </div> 
</form> 

4.验证规则相关 [required/minlength/maxlength等]

<form #f='ngForm' novalidate (ngSumbit)='onSubmit(f)'>
  <input  type='text'
       name='username'
       [(ngModel)]='login.username' 
          #username='ngModel'
           minlength='8'>
  <div *ngIf='username.error?.minlength && username.touched' class='error'>
    The minlength is 8.
 </div> 
</form> 

5.验证状态相关 [touched/valid/invalid/pristine/dirty/untouched等]

valid:控件有效

invalid:控件无效

pristine:控件值未改变

dirty:控件值已改变

untouched:表单控件未被访问过

<form novalidate #f='ngForm'>
    ...
   <button type='submit' 
           [disabled]='f.invalid'           (click)='onSubmit(f)'>
           submit
  </button>
</form>        

二:Reactive Forms (Model-Driven Forms) - 响应式表单 [引入ReactiveFormsModule]

1.FormGroup(FormControl+FormArray)[表单对象]

FormGroup包含一组FormControl和FormArray的实例,可用于跟踪一组实例的值和验证状态

FormControl & FormArray:为单个表单控件提供支持的类,用于跟踪控件的值和验证状态 前者是单值类型,后者是多值类型

<form novalidate [formGroup]='thatForm'>
    <input type='text' formControlName='name'>
</form>

2.Validators [表单验证]

//html方面
<form novalidate [formGroup]='thatForm'> <input type='text' formControlName='name'> <div class='error' *ngIf="thatForm.get('name').hasError('required') && thatForm.get('name').touched"> Name is required </div> <div class='error' *ngIf="thatForm.get('name').hasError('minlength') && thatForm.get('name').touched"> The minlength is 2. </div> </form>
//xx.component.ts

export class xxComponent implements OnInit{
    thatForm: FormGroup;
    constructor(){};
   ngOnInit() {
    this.thatForm=new FormGroup({
       name:new FormGroup('',[Validators.required,Validators.minLength(2)])     
   })      
  }
}     

3.FormBuilder [简化新建FormGroup对象整个过程]

//FormGroup用法

export class xxComponent implements OnInit{
    thatForm: FormGroup;
    constructor(){};
   ngOnInit() {
    this.thatForm=new FormGroup({
      name:new FormGroup('',[Validators.required,Validators.minLength(2)])     
   })       }
}   
//FormBuilder用法

export class xxComponent implements OnInit{
    thatForm: FormGroup;
    constructor(private formBuilder: FormBuilder){};
   ngOnInit() {
      this.thatForm=this.formBuilder.group({
          name:['',[Validator.required,Validators.minLength(2)]]
     })
   }
} 

4.FormValidation [统一管理验证错误]

//html方面
<form novalidate [formGroup]='thatForm'>
    <input type='text' formControlName='name'>
    <div class='error'>
      {{formValidation.msgs.name.errors}}
    </div>
</form>
//form-validation.ts

export class xxValidation extends FormValidation{
   constructor(){
     super()
  }
  msgs={
    name:{
      errors:'',
      messages:{ 
         required:'please type the name.',
         minlength:'please enter 3 charactors atleast.'
     }
   }
 }
}
//xx.component.ts

export class xxComponent implements OnInit{
    formValidation:xxValidation=new xxValidation();
     thatForm:FormGroup;

    constructor(private formBuilder: FormBuilder){}
     ngOnInit(){
      this.thatForm=this.formBuilder.group({
       name:['',[Validators.required,Validators.minLength(4)]] 
     })
   }
   
}

两种方式的比较:

模板驱动表单(Template-Driven Forms)

1.使用方便

2.适用于简单的场景

3.通过[(ngModel)]实现数据双向绑定

4.最小化组件类的代码

5.不利于单元测试

响应式表单(Reactive Forms)

1.比较灵活

2.适用于复杂的场景

3.简化了HTML模板的代码,把验证逻辑抽离出来了

4.方便跟踪表单控件值的变化

5.易于单元测试