Angular表单之响应式表单

简介

angular的表单分响应式表单和模板驱动表单,响应式表单和模板驱动表单的区别在官网上是这么讲的

  • 响应式表单更健壮:它们的可扩展性、可复用性和可测试性更强。 如果表单是应用中的关键部分,或者你已经准备使用响应式编程模式来构建应用,请使用响应式表单
  • 模板驱动表单在往应用中添加简单的表单时非常有用,比如邮件列表的登记表单。它们很容易添加到应用中,但是不像响应式表单那么容易扩展。如果你有非常基本的表单需求和简单到能用模板管理的逻辑,请使用模板驱动表单

使用

导入模块

在使用响应式表单之前应该在需要的模块中导入ReactiveFormsModule,可以在特定的模块中导入,也可以自在根模块(AppModule)中导入。
例如直接在根模块下导入

// 导入ReactiveFormsModule
import {ReactiveFormsModule} from '@angular/forms';

@NgModule({
  declarations: [
    AppComponent,
    NameEditorComponent,
    ProfileEditorComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    // 响应式表单需要的导入的模块
    ReactiveFormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})

对象

在响应式表单中提供了几种对象,分别为
FormControl: Angular 表单的三大基本构造块之一
FormGroup:Angular 表单的三大基本构造块之一
FormArray:Angular 表单的三大基本构造块之一
FormBuilder:以简化 FormControl、FormGroup 或 FormArray 实例的创建过程。有三个方法:control()、group() 和 array()。这三个方法都是工厂方法,用于在组件类中分别生成 FormControl、FormGroup 和 FormArray

FormControl

Formcontrol可以单独使用,也可以和FormGroup一起使用,

单独使用FormControl

export class NameEditorComponent implements OnInit {

  // 生成一个FormControl实例
  name = new FormControl('');
  constructor() { }
  ngOnInit() {
  }

}

所对应的html的内容

<label>
  Name:
  <input type="text" [formControl]="name">
</label>
<p>{{name.value}}</p>

注意:单独使用FormControl的时候input标签不要放在form标签里面,不然会报错,至于为什么会报错,我也不知道,如果有知道的可以帮忙解答下

与FormGroup一起使用

export class NameEditorComponent implements OnInit {

  myGroup = new FormGroup({
    name: new FormControl('')
  });

  constructor() { }

  ngOnInit() {
  }

}

所对应的html

<form [formGroup]="myGroup">
  <label>
    Name:
    <input type="text" formControlName="name">
  </label>

  <p>{{myGroup.value | json}}</p>
</form>

在这里可以添加form标签不会报错

FormGroup

FormGroup是Angular 表单的三大基本构造块之一,可以把FormGroup看做一个容器,FormGroup可以嵌套其他的构造块,FormGroup可以嵌套FormGroup,并且一直嵌套下去。
例子如下

export class ProfileEditorComponent implements OnInit {

  profileForm = new FormGroup({
    firstName: new FormControl(''),
    lastName: new FormControl(''),
    address: new FormGroup({
      street: new FormControl(''),
      city: new FormControl(''),
      state: new FormControl(''),
      zip: new FormControl('')
    }),
    aliases: new FormArray([
      new FormControl('')
    ])
  });

  get aliases() {
    return this.profileForm.get('aliases') as FormArray;
  }

  constructor() { }

  ngOnInit() {
  }
  
}

所对应的html代码如下

<form [formGroup]="profileForm" (ngSubmit)="onSubmit()">
  <div>
    <label>
      First Name: <input type="text" formControlName="firstName"/>
    </label>
  </div>
  <div>
    <label>
      Last Name: <input type="text" formControlName="lastName">
    </label>
  </div>
  <div formGroupName="address">
    <h3>Address</h3>
    <div>
      <label>
        Street: <input type="text" formControlName="street">
      </label>
    </div>
    <div>
      <label>
        City: <input type="text" formControlName="city">
      </label>
    </div>
    <div>
      <label>
        State: <input type="text" formControlName="state">
      </label>
    </div>
    <div>
      <label>
        Zip Code: <input type="text" formControlName="zip">
      </label>
    </div>
  </div>
  <div formArrayName="aliases">
    <div *ngFor="let address of aliases.controls; let i=index">
      <label>
        Alias{{i}}:
        <input type="text" [formControlName]="i">
      </label>
    </div>
  </div>
</form>

FormArray

FormArray可以管理任意数量的匿名控件,例如可以使用在高级搜索中添加搜索字段等。

在上面的代码中添加

  //添加一个新的输入框
  addAlias() {
    this.aliases.push(this.formBuilder.control(''));
  }

对应的html添加

<h3>Aliases</h3> 
<button type="button" (click)="addAlias()">添加输入框</button>

FormBuilder

FormBuilder一般作为一个工厂来使用,通过FormBuilder来创建FormControl、FormGroup、FormArray实例

export class ProfileEditorComponent implements OnInit {

  // profileForm = new FormGroup({
  //   firstName: new FormControl(''),
  //   lastName: new FormControl(''),
  //   address: new FormGroup({
  //     street: new FormControl(''),
  //     city: new FormControl(''),
  //     state: new FormControl(''),
  //     zip: new FormControl('')
  //   }),
  //   aliases: new FormArray([
  //     new FormControl('')
  //   ])
  // });

  profileForm = this.formBuilder.group({
    firstName: ['', Validators.required],
    lastName: [''],
    address: this.formBuilder.group({
      street: [''],
      city: [''],
      state: [''],
      zip: ['']
    }),
    aliases: this.formBuilder.array([
      this.formBuilder.control('')
    ])
  });

  get aliases() {
    return this.profileForm.get('aliases') as FormArray;
  }

  constructor(private formBuilder: FormBuilder) { }

  ngOnInit() {
  }
  
  //...


}

可以看到通过FormBuilder创建Angular 表单的三大基本构造块比通过new方法去构建代码简洁了许多

更改表单的值

在使用Angular的响应式表单的时候,修改表单的值与使用模板驱动表单去修改表单的值不同,需要使用patchValue或者setValue方法进行修改。

setValue

setValue是修改整个表单模型,并且需要严格按照表单组的结构

export class ProfileEditorComponent implements OnInit {
  //..
  updateProfileForm() {  
    this.profileForm.setValue({
      firstName: 'firstName',
      lastName: 'lastName',
      address: {
        street: 'street',
        city: 'city',
        state: 'state',
        zip: 'zip'
      },
      aliases: [
        'hello 1'
      ]
    })
  }
}

如果这个结构与表单模型的结构不同,那么就会修改出错,例如在这个表单模型中,虽然现在可以用,但是因为里面有FormArray,但添加一个新的输入框的时候,那个就不能该修改了,因为aliases属性里面的内容与表单模型已经不符合了。

setValue在修改单个的比较好用,在修改一组的时候并不是特别好用,因为有可能只需要修改里面的一个,却需要把所有的结构写好,这样就比较浪费时间,但是由于它对于结构的要求非常的严格,所以出错率也非常的低(结构不对运行不了,所以写错了可以马上发现)

patchValue

patchValue与setValue不同,它可以只修改部分内容

export class ProfileEditorComponent implements OnInit {

  updateProfileForm() {
    this.profileForm.patchValue({
      firstName: 'hello world',
      hello: 'hello',
      address: {
        street: 'ha'
      }
    });
  }
}

这里面的hello属性在profileForm里面是没有的,但程序运行仍然不会报错,所以出错率比较高(在修改值的时候写错了一个字母,却不见任何错误,就是不见效果,所以这个就需要比较注意)

全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务