Angular 表单processing

Master Angular 模板驱动表单 and response式表单两种表单processing方式

Angular 表单overview

Angular providing了两种表单processing方式: 模板驱动表单 and response式表单.

提示

模板驱动表单适合 simple 表单, response式表单适合 complex 表单 and 需要动态控制 表单.

1. 模板驱动表单

模板驱动表单 is through模板in 指令来creation and management表单 , 它 特点 is simple 易用, 适合 fast 速Development simple 表单.

1.1 启用模板驱动表单

要using模板驱动表单, 需要先import FormsModule:

// app.module.ts
import { FormsModule } from '@angular/forms';

@NgModule({
  imports: [
    BrowserModule,
    FormsModule // import FormsModule
  ],
  // ...
})
export class AppModule { }

1.2 creation模板驱动表单

// user-form.component.html

1.3 processing表单submitting

// user-form.component.ts
import { Component } from '@angular/core';
import { NgForm } from '@angular/forms';

@Component({
  selector: 'app-user-form',
  templateUrl: './user-form.component.html',
  styleUrls: ['./user-form.component.css']
})
export class UserFormComponent {
  onSubmit(form: NgForm) {
    if (form.valid) {
      console.log('表单data: ', form.value);
      // submitting表单data to server
    }
  }
}

2. response式表单

response式表单 is throughcode来creation and management表单 , 它 特点 is flexible强 big , 适合 complex 表单 and 需要动态控制 表单.

2.1 启用response式表单

要usingresponse式表单, 需要先import ReactiveFormsModule:

// app.module.ts
import { ReactiveFormsModule } from '@angular/forms';

@NgModule({
  imports: [
    BrowserModule,
    ReactiveFormsModule // import ReactiveFormsModule
  ],
  // ...
})
export class AppModule { }

2.2 creationresponse式表单

// user-reactive-form.component.ts
import { Component, OnInit } from '@angular/core';
import { Formbuilder, FormGroup, Validators } from '@angular/forms';

@Component({
  selector: 'app-user-reactive-form',
  templateUrl: './user-reactive-form.component.html',
  styleUrls: ['./user-reactive-form.component.css']
})
export class UserReactiveFormComponent implements OnInit {
  userForm: FormGroup;

  constructor(private fb: Formbuilder) { }

  ngOnInit(): void {
    // using Formbuilder creation表单组
    this.userForm = this.fb.group({
      name: ['', [Validators.required, Validators.minLength(3), Validators.maxLength(20)]],
      email: ['', [Validators.required, Validators.email]],
      age: [18, [Validators.required, Validators.min(18), Validators.max(100)]],
      gender: ['male', Validators.required],
      address: this.fb.group({
        street: ['', Validators.required],
        city: ['', Validators.required],
        zipCode: ['', Validators.required]
      })
    });
  }

  onSubmit() {
    if (this.userForm.valid) {
      console.log('表单data: ', this.userForm.value);
      // submitting表单data to server
    }
  }
}

2.3 response式表单模板

// user-reactive-form.component.html
姓名 is 必填项
姓名至 few 需要3个字符
姓名最 many 只能20个字符
邮箱 is 必填项
请输入 has 效 邮箱地址

地址information

3. 表单verification

Angular providing了 many 种表单verification方式, including in 置verification器 and 自定义verification器.

3.1 in 置verification器

Angular providing了以 under in 置verification器:

  • required: 必填项
  • minlength: 最 small long 度
  • maxlength: 最 big long 度
  • min: 最 small 值 (用于number)
  • max: 最 big 值 (用于number)
  • email: 邮箱格式
  • pattern: 正则表达式匹配

3.2 自定义verification器

可以creation自定义verification器来满足specific verificationrequirements:

// custom-validators.ts
import { AbstractControl, ValidationErrors } from '@angular/forms';

export function forbiddenNameValidator(forbiddenName: string): ValidatorFn {
  return (control: AbstractControl): ValidationErrors | null => {
    const forbidden = control.value && control.value.toLowerCase() === forbiddenName.toLowerCase();
    return forbidden ? { forbiddenName: { value: control.value } } : null;
  };
}

export function passwordMatchValidator(control: AbstractControl): ValidationErrors | null {
  const password = control.get('password');
  const confirmPassword = control.get('confirmPassword');
  
  if (!password || !confirmPassword) {
    return null;
  }
  
  return password.value === confirmPassword.value ? null : { passwordMismatch: true };
}

3.3 using自定义verification器

// register-form.component.ts
import { Component, OnInit } from '@angular/core';
import { Formbuilder, FormGroup, Validators } from '@angular/forms';
import { forbiddenNameValidator, passwordMatchValidator } from '../custom-validators';

@Component({
  selector: 'app-register-form',
  templateUrl: './register-form.component.html',
  styleUrls: ['./register-form.component.css']
})
export class RegisterFormComponent implements OnInit {
  registerForm: FormGroup;

  constructor(private fb: Formbuilder) { }

  ngOnInit(): void {
    this.registerForm = this.fb.group({
      username: ['', [
        Validators.required,
        Validators.minLength(3),
        forbiddenNameValidator('admin') // using自定义verification器
      ]],
      email: ['', [Validators.required, Validators.email]],
      password: ['', [Validators.required, Validators.minLength(6)]],
      confirmPassword: ['', Validators.required]
    }, { validator: passwordMatchValidator }); // using跨字段verification器
  }

  onSubmit() {
    // processing表单submitting
  }
}

4. 表单控件status

Angular 表单控件 has 以 under status:

  • dirty: 控件值已被modify
  • pristine: 控件值未被modify
  • touched: 控件已被触摸 (获得焦点 after 失去焦点)
  • untouched: 控件未被触摸
  • valid: 控件值 has 效
  • invalid: 控件值无效
  • pending: 控件verification正 in forin

5. 动态表单

response式表单可以easilycreation动态表单, 例such as动态添加 or delete表单控件:

// dynamic-form.component.ts
import { Component, OnInit } from '@angular/core';
import { FormArray, Formbuilder, FormGroup, Validators } from '@angular/forms';

@Component({
  selector: 'app-dynamic-form',
  templateUrl: './dynamic-form.component.html',
  styleUrls: ['./dynamic-form.component.css']
})
export class DynamicFormComponent implements OnInit {
  dynamicForm: FormGroup;

  constructor(private fb: Formbuilder) { }

  ngOnInit(): void {
    this.dynamicForm = this.fb.group({
      name: ['', Validators.required],
      hobbies: this.fb.array([
        this.fb.control('', Validators.required)
      ])
    });
  }

  get hobbies() {
    return this.dynamicForm.get('hobbies') as FormArray;
  }

  addHobby() {
    this.hobbies.push(this.fb.control('', Validators.required));
  }

  removeHobby(index: number) {
    if (this.hobbies.length > 1) {
      this.hobbies.removeAt(index);
    }
  }

  onSubmit() {
    // processing表单submitting
  }
}

5.1 动态表单模板

// dynamic-form.component.html

爱 good

6. 表单 best practices

  1. 根据表单 complexity选择合适 表单class型: simple 表单using模板驱动表单, complex 表单usingresponse式表单
  2. 始终添加表单verification, improvinguser体验 and dataquality
  3. providing清晰 errorinformation, helpinguser修正表单
  4. using表单组 (FormGroup) 组织相关 表单控件
  5. for 于动态表单, using FormArray management动态添加 表单控件
  6. using自定义verification器processing complex verification逻辑
  7. in submitting表单 before check表单 has 效性
  8. using表单status样式providing视觉反馈

练习 1: creation模板驱动表单

  1. creation一个userregister表单, package含姓名, 邮箱, password and 确认password字段
  2. 添加适当 verification规则:
    • 姓名: 必填, 3-20个字符
    • 邮箱: 必填, has 效 邮箱格式
    • password: 必填, 至 few 6个字符
    • 确认password: 必填, and password一致
  3. 显示相应 errorinformation
  4. 只 has 当表单 has 效时, submitting按钮才可点击

练习 2: creationresponse式表单

  1. creation一个产品表单, package含产品名称, 价格, describes and tag字段
  2. using Formbuilder creation表单
  3. 添加适当 verification规则:
    • 产品名称: 必填, 2-50个字符
    • 价格: 必填, big 于0 number
    • describes: 必填, 至 few 10个字符
    • tag: 至 few 添加一个tag
  4. implementation动态添加 and deletetag functions
  5. 显示相应 errorinformation