8

angular-road

Angular 中有两种表单:

  • Template-driven Forms (类似于 AngularJS 1.x 中的表单 )

  • Reactive Forms

Template-driven 表单的特点

  • 使用方便

  • 适用于简单的场景

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

  • 自动生成 Form Model (异步)

  • 最小化组件类的代码

  • 不易于单元测试

Reactive 表单的特点

  • 比较灵活

  • 适用于复杂的场景

  • 简化了HTML模板的代码,把验证逻辑抽离到组件类中

  • 手动创建 Form Model (同步)

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

  • 易于动态添加表单控件

  • 易于单元测试

Template-driven vs Reactive 表单

Template-driven 表单

  • 模板

    • Form 元素

    • Input 元素

    • 数据绑定

    • 验证规则 (属性设置,如 required)

    • 错误消息

    • 自动创建对应的表单模型 (如 FormGroup、FormControl)

  • 组件类

    • 属性绑定

    • 表单操作相关的方法,如表单提交 (submit)

  • 指令 (FormsModule)

    • ngForm

    • ngModel

    • ngModelGroup

Reactive 表单

  • 模板

    • Form 元素

    • Input 元素

    • Form 模型绑定

  • 组件类

    • Form 模型

    • 验证规则

    • 错误消息

    • 数据模型相关属性

    • 表单操作相关的方法,如表单提交 (submit)

  • 指令 (ReactiveFormsModule)

    • formGroup

    • formControl

    • formControlName

    • formGroupName

    • formArrayName

表单控件的状态

  • Value Changed

    • pristine - 表单控件值未改变

    • dirty - 表单控件值已改变

  • Validity

    • valid - 表单控件有效

    • invalid - 表单控件无效

  • Visited

    • touched - 表单控件已被访问过

    • untouched - 表单控件未被访问过

HTML Form vs Template-driven Form vs Reactive Form

HTML Form

<form>
  <div>
    <label>
      <span>用户名</span>
      <input
        type="text"
        name="userName"
        placeholder="请输入用户名">
    </label>
  </div>
  ...
  <button type="submit">注册</button>
</form>

Template-driven Form

<form (ngSubmit)="save(signupForm)" #signupForm="ngForm">
  <div>
    <label>
      <span>用户名</span>
      <input type="text" name="userName"
        placeholder="请输入用户名"
        required minlength="3"
        [(ngModel)]="user.userName"
        #userName="ngModel">
    </label>
    <div *ngIf="userName.touched && userName.errors?.required">
      用户名是必填项
    </div>
    <div *ngIf="userName.touched && userName.errors?.minlength">
      用户名的长度必须大于3
    </div>
  </div>
  ...
  <button type="submit">注册</button>
</form>

Reactive Form

<form (ngSubmit)="save()" [formGroup]="signupForm">
  <div>
    <label>
      <span>用户名</span>
      <input type="text" name="userName"
        placeholder="请输入用户名"
        formControlName="userName">
    </label>
    <div *ngIf="signupForm.get('userName').touched && 
        signupForm.get('userName').hasError('required')">
            用户名是必填项
    </div>
    <div *ngIf="signupForm.get('userName').touched && 
        signupForm.get('userName').hasError('minlength')">
            用户名的长度必须大于3
    </div>
  </div>
  ...
  <button type="submit" [disabled]="signupForm.invalid">注册</button>
</form>

接下来我们主要来介绍一下 Reactive Form 的一些相关基础知识。

Reactive Form 简介

使用 Reactive Form

要使用 Reactive Form 需要以下几个步骤:

  • 导入 ReactiveFormsModule

import { ReactiveFormsModule } from "@angular/forms";
  • 在 NgModule 的 imports 属性值对应的数组中,添加 ReactiveFormsModule

@NgModule({
  imports: [
    BrowserModule,
    ReactiveFormsModule
  ],
})
export class AppModule { }
  • 绑定 form 元素的 formGroup 属性

<form (ngSubmit)="save()" [formGroup]="signupForm"></form>
  • 关联 input 元素对应的 FormControl 实例

<input type="text" name="userName" placeholder="请输入用户名" 
  formControlName="userName">

使用 FormGroup

  • 创建 FormGroup 属性

  • 创建 FormGroup 实例

  • 创建每个 FormControl 实例

signupForm: FormGroup; 

this.signupForm = new FormGroup({
  userName: new FormControl('', [Validators.required, Validators.minLength(3)]),
  email: new FormControl('', [Validators.required, Validators.email]),
  ...
});

使用 FormBuilder

要使用 FormBuilder 需要以下几个步骤:

  • 导入 FormBuilder

  • 注入 FormBuilder 实例

  • 使用 FormBuilder 实例

FormBuilder 创建 Form Control 语法

  • 方式一

this.signupForm = this.fb.group({
  userName: 'semlinker',
  hasAddress: false
});
  • 方式二

this.signupForm = this.fb.group({
  userName: {value: 'semlinker', disabled: true}
  hasAddress: {value: true, disabled: false}
});
  • 方式三

this.signupForm = this.fb.group({
  userName: [''],
  hasAddress: [{value: true, disabled: false}]
})

进阶资源

若想进一步阅读更多表单相关的资料,请查看 Angular 4修仙目录 - 表单章节


阿宝哥
15.8k 声望10.2k 粉丝

聚焦全栈,专注分享 Angular、TypeScript、Node.js/Java 、Spring 技术栈等全栈干货


引用和评论

1 篇内容引用
0 条评论