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

全部评论

相关推荐

感觉这一周太梦幻了,就像一个梦,很不真实~~~感觉这个暑期,我的运气占了99成,实力只有百分之一4.15上午&nbsp;腾讯csig&nbsp;腾讯云部门,面完秒进入复试状态4.16下午&nbsp;美团优选供应链部门,4.18上午发二面4.17晚上&nbsp;阿里国际一面,纯拷打,面完我都玉玉了4.18下午&nbsp;阿里国际二面,是我们leader面的我,很轻松~~4.18晚上&nbsp;约了hr面4.19上午&nbsp;hr面,下午两点口头oc4.19晚上&nbsp;意向书说起来我的暑期好像一次都没挂过~~~~~难道我是天生面试圣体?----------------------------------------------------------------------六个月前,我还是0项目0刷题,当时想的是先把论文发出来再去找实习。结果一次组会,老师打破了我的幻想(不让投B会,只让投刊或者A)我拿头投啊!!!然后就开始物色着找实习,顺便做完了mit的6.s081,但是基本上还是没刷过题目-----------------------------------------------------------------------11月&nbsp;&nbsp;一次偶然的机会,面进了某个耳机厂的手环部门,大概是做嵌入式的,用的是CPP。12月&nbsp;莫名其妙拿到了国创的面试机会,0基础四天速成java基础!居然也给我面过了hhhhh,可能是面试没写题吧入职国创后的几个月,一直没活,天天搁那看剧,都快忘了还有暑期实习这回事了~~~~命运的齿轮在2.26开始转动,因为这一天美团开了,我开始慌了,因为那时的我什么都不会。lc,八股,sql全部是0进度。然后就开始了女娲补天,上班刷题,下班继续做之前的开源,顺便学一学八股。3月到现在,lc也刷到快200了,一天最多提交了47次~~~~~~~~~~八股根据别人的面经总结和博客,写了快十万字的笔记~~~~~~~~~~简历上的实习经历和开源,也努力去深挖了,写了几万字的记录~~~~~~所以面试的时候,基本上都能cover了,面试官问到的基础基本都会,不基础的我就把他往我会的地方引。结果好像还不错,基本上每个面试官评价都挺好的emmmmmmmm
投递阿里巴巴等公司10个岗位
点赞 评论 收藏
转发
点赞 收藏 评论
分享
牛客网
牛客企业服务