继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Angular响应式表单指南:轻松构建复杂表单的实用教程

素胚勾勒不出你
关注TA
已关注
手记 334
粉丝 53
获赞 274

本文是一份关于 Angular 中反应式表单(Reactive Forms)的各种可能性的全面指南。首先,在这一部分中,我们将了解反应式表单的优势、如何创建一个表单、不同的验证方法,以及反应式表单与 Observables 之间的联系。

为什么用响应式表单?

为了开始,我们先来理解一下为什么会出现响应式表单。这里有一个基本的响应式表单的例子。

  • HTML模版
     <div class="form-wrapper">  

      <h1>注册表单范例</h1>  

      <form (submit)="handleSubmit($event)">  

        <input type="text" placeholder="用户名称" id="username" class="form-field-input" />  
        <input type="password" placeholder="密码" id="password" class="form-field-input"/>  
        <button type="submit" class="button-primary">去注册</button>  

      </form>  

    </div>
  • TypeScript 组件
@Component({  
  selector: 'app-root',  
  templateUrl: './app.component.html',  
  styleUrls: './app.component.scss'  
})  
export class AppComponent implements OnInit {  

  usernameInput!: HTMLInputElement;  
  passwordInput!: HTMLInputElement;  

  ngOnInit(): void {  
    // 在 UI 上出现后获取输入元素  
    this.usernameInput = document.getElementById('username') as HTMLInputElement;  
    this.passwordInput = document.getElementById('password') as HTMLInputElement;  
  }  

  handleSubmit(event: Event) {  

    // 阻止表单在提交时重新加载  
    event.preventDefault();  

    // 处理提交的数据  
    const submitData = {  
      username: this.usernameInput.value,  
      password: this.passwordInput.value  
    }  

    // 在控制台打印提交的数据  
    console.log('submitData :>> ', submitData);  
    // 例如:{ username: "PezoInTheHouse", password: ****** }  
  }

没问题!
这种方法对于非常简单的表单来说没问题。然而,在实际中,我们构建的表单要复杂很多。

挑战:表单验证问题
  • TypeScript 组件
      usernameErrorMessage = ''  
      passwordErrorMessage = ''  

      handleSubmit(event: Event) {  

        // 阻止表单在提交时重新加载  
        event.preventDefault();  

        // 验证用户名:  
        if (!this.usernameInput.value) {  
          this.usernameErrorMessage = '用户名是必填的!';  
          return;  
        }  

        if (this.usernameInput.value.length > 20) {  
          this.usernameErrorMessage = '用户名太长了!';  
          return;  
        }  

        // 验证密码:  
        if (!this.passwordInput.value) {  
          this.passwordErrorMessage = '密码是必填的!';  
          return;  
        }  

        if (this.passwordInput.value.length > 20) {  
          this.passwordErrorMessage = '密码太长了!';  
          return;  
        }  

        // 处理表单数据如下:  
        const submitData = {  
          username: this.usernameInput.value,  
          password: this.passwordInput.value  
        }  

        console.log('提交的数据:', submitData);  
      }
  • HTML模版
     <div class="form-wrapper">  

      <h1>注册表单示例</h1>  

      <form (submit)="handleSubmit($event)">  

        <input type="text" placeholder="用户名" id="username" class="form-field-input" />  
        @if (!!usernameErrorMessage) {  
          <p class="error-text">{{ usernameErrorMessage }}</p>  
        }  

        <input type="password" placeholder="密码" id="password" class="form-field-input"/>  
        @if (!!passwordErrorMessage) {  
          <p class="error-text">{{ passwordErrorMessage }}</p>  
        }  

        <button type="submit" class="button-primary">注册</button>  
      </form>  

    </div>

它确实能工作。然而,今天你几乎找不到这样的情况,即在提交后却发现每个字段都显示错误。

更直观的做法是在输入框输入无效内容(在用户交互之后)时显示错误。这意味着我们需要手动处理输入框上的各种事件变化,以跟踪这些变化。

    <input type="text" placeholder="用户名:" class="form-field-input"  
      (blur)="handleTouchEvent()" (change)="handleChange()"  
      [value]="latestValue"/>
  • 我们可以为密码字段设置不同的验证规则,比如要求包含字母、数字和特殊字符的组合。
  • 此外,用户名字段可以与一个API交互,以检查该用户名是否已经存在。
  • 同时,我们还需要考虑性能问题。我们不想在每次按键时都进行文本验证或调用API,应该设置节流机制。
  • 如果有密码和重复密码两个字段,我们需要验证这两个字段的值是否一致。

这些小要求使得手动编写这一切变成了一场活生生的噩梦。我们需要手动检查所有字段间的验证规则。监听 DOM 事件来确定触发的是什么以及何时触发之类的。

肯定有更好的办法来处理这个问题。你知道吗?响应式表单就是答案。

开始使用反应式表单

现在咱们来看看响应式表单和其他表单有什么不一样。

步骤 1

在你的 AppModule 中导入 ReactiveFormsModule

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

    @NgModule({  
      declarations: [AppComponent],  
      bootstrap: [AppComponent],  
      imports: [  
        BrowserModule,  
        AppRoutingModule,  
        ReactiveFormsModule, // <-- 这里就是它所在的位置  
    ],  
      providers: [],  
    })  
    export class AppModule {}

如果你使用的是独立组件的话,这样的话,你需要将该模块导入到 imports 数组里。

    import { Component } from '@angular/core';  
    import { ReactiveFormsModule } from '@angular/forms';  

    @Component({  
      selector: 'app-root',  
      standalone: true,  
      imports: [  
        CommonModule,   
        ReactiveFormsModule // <-- 这里就是了  
      ],  
      templateUrl: './app.component.html',  
      styleUrl: './app.component.scss',  
    })  
    export class AppComponent
步骤2

反应式表单采用基于模型的表单创建方式,您可以在TypeScript组件中创建表单模型、控件和验证逻辑,并将它们绑定到模板。
这可以通过在Angular中使用FormBuilder类来实现,通过将其添加到组件构造函数中,可以注入该类。

    constructor(private fb: FormBuilder) {}

此表单是一个由多个 FormControl(每个表单字段一个)或 FormGroup 组成的 FormGroup

    signUpForm!: FormGroup;  

    this.signUpForm = this.fb.group({  
      username: [''],  
      密码: [''],  
    });

每个表单字段都是一个在创建表单时添加的 FormControl。也就是说,表单控件和组之后可以通过 FormArrays 添加或移除,我们将在第二部分更详细地了解 FormArrays

示例如下:

import { FormBuilder, FormGroup } from '@angular/forms';

@Component({  
  selector: 'app-root',  
  templateUrl: './app.component.html',  
  styleUrl: './app.component.scss'  
})  
export class AppComponent implements OnInit {  
  registerForm!: FormGroup;  

  constructor(private fb: FormBuilder) {}  

  ngOnInit(): void {  
    this.registerForm = this.fb.group({ // 表单对象  
      username: [''], // 表单控件  
      password: [''], // 表单控件  
    });  
  }  

  handleSubmission() {  
    const formValue = this.registerForm.value;  

    console.log('表单值:', formValue);  
  }

## 步骤三

绑定 TypeScript 组件:模板

* 将表单组控件绑定到表单 HTML 元素: `[formGroup]="signUpForm"` 
* 将每个表单控件绑定到输入框: 
(`formControlName="username"`,`formControlName="password"`)
* 将提交按钮事件绑定到在组件中创建的提交处理方法: `(submit)="handleSubmit()"`
<div class="form-wrapper">  

  <h1>注册表单示例</h1>  

  <form (submit)="handleSubmit()" [formGroup]="signUpForm">  

    <input type="text" placeholder="用户名(请输入用户名)" formControlName="username" class="form-field-input" />  
    <input type="password" placeholder="密码(请输入密码)" formControlName="password" class="form-field-input"/>  

    <button type="submit" class="button-primary">立即注册</button>  
  </form>  

</div>

一旦表单模型创建并与模板关联,对表单控件所做的任何更改都会自动反映在表单状态上,而无需手动处理显式的事件。

![](https://imgapi.imooc.com/674fb05809c095fe05520511.jpg)

我们也无需担心在提交时防止表单重复加载,因为 Angular 自动帮我们处理了这个问题。

# 表单验证

让我们通过增加表单验证来扩展这个例子。响应式表单提供了一系列常用的验证函数:

* 必填项
* 最小/最大长度(字符)
* 最小/最大值(数字)
* 正则匹配(使用正则表达式)

一个将所需验证器添加到控件元素中的示例:

// 导入 Angular 表单模块
import { FormBuilder, FormGroup, Validators } from '@angular/forms';

// 初始化注册表单
ngOnInit(): void {
this.signUpForm = this.fb.group({
// 用户名字段,必填验证
username: ['', Validators.required],
// 密码字段
password: [''],
});
}


我们可以通过 `FromGroup` 的 `valid` 属性来检查它的有效性。
提交表单() {  

  const 表单有效 = this.signUpForm.valid;  
  console.log('表单有效 :>> ', 表单有效);  

  if (!表单有效) {  
    return;  
  }  

  const 表单值 = this.signUpForm.value;  
  console.log('表单值 :>> ', 表单值);  
}

在添加用户名之前点击提交按钮会使表单无效。如果添加了用户名,表单就会有效。

![](https://imgapi.imooc.com/674fb05a09691ef308780587.jpg)

有效性可以通过验证 `FormControl` 来确认。首先,我们需要从表单中提取 `FormControl` 用户名,这可以通过在 `FormGroup` 上使用 `get()` 属性来实现。

import {
AbstractControl,
FormBuilder,
FormGroup,
Validators,
} from '@angular/forms';

// 获取 'username' 字段
const usernameControl = this.signUpForm.get('username') as AbstractControl;


现在,我们来看看 `username` 控制的有效性和值如何。
handleSubmit() {  

  const usernameControl = this.signUpForm.get('username') as AbstractControl;  

  console.log(usernameControl.value); // 用户名控件的值  
  console.log(usernameControl.valid); // 为空时为 false,非空时为 true  
}

## 扩展控制和验证功能:
```python
# Example code segment remains unchanged

每个 FormControl 都可以拥有一组同步验证器和异步验证器。它们还可以有一个默认值会在字段中显示。

this.fb.group({
  username: [
    '默认值(DEFAULT VALUE)',
    [
      /* 同步验证器: */
    ],
    [
      /* 异步验证器: */
    ],
  ],
  ...
});

现在应用到注册表:

ngOnInit(): void {  
  this.signUpForm = this.fb.group({  
    username: ['', [Validators.required, Validators.minLength(3), Validators.maxLength(24)]],  
    password: ['', [Validators.required, Validators.minLength(10)]],  
    age: ['', [Validators.min(12), Validators.pattern("^[0-9]*$")]], // 只允许输入数字  
    rememberMe: [true]  // 记住我 [复选框]  
  });  
}

请提供要翻译的具体英文文本。删除此行。

正确的翻译应在提供完整英文文本后给出。

  • username 是必填项,长度需在 3 到 24 个字符之间。
  • password 同样是必填项,长度需至少 10 个字符。
  • age 是可选的,但只接受数字。
  • rememberMe 是可选的,默认选中(true)。
HTML模板中的表单相关样式

我们来用新的组件更新模板中的控件

    <div class="form-wrapper">  

      <h1>注册示例</h1>  

      <form (submit)="handleSubmit()" [formGroup]="signUpForm">  

        <input type="text" placeholder="用户名" formControlName="username" class="form-field-input" />  
        <input type="password" placeholder="密码" formControlName="password" class="form-field-input"/>  
        <input type="number" placeholder="年龄" formControlName="age" class="form-field-input"/>  
        <div>  
          <input type="checkbox" formControlName="rememberMe" /> 记住我?  
        </div>  

        <button type="submit" class="button-primary">注册</button>  
      </form>  

    </div>

在元素检查器视图中,你也能清楚地看到组件中的控制设置。

正如开发工具所显示的,usernamepassword 这两个输入框带有 ng-invalid 类,这表明它们无效,导致整个表单无法通过验证。

你可以通过在模板里加上无效的验证检查来验证这一点。

    <input type="text" placeholder="用户名" formControlName="username" class="form-field-input" />  
    @if (signUpForm.get('username')?.invalid) {  
      <p class="error-text">用户名不能为空!</p>  
    }  

    <input type="password" placeholder="密码" formControlName="password" class="form-field-input"/>  
    @if (signUpForm.get('password')?.invalid) {  
      <p class="error-text">密码不能为空!</p>  
    }

页面加载时,这样的错误就会出现。

这不是一个很好的用户体验。如果在用户与这些字段互动后才显示错误,体验会更好。我们再来看看检查元素的视图,看看发生了什么。

页面加载时,与表单组件相关的每个元素都会有一组 Angular 表单类:

  • 未输入
  • 初始状态

这表明表单字段未被改动,也没有任何内容填写。相反的情况则是:

  • ng-触(用户点击或触碰了字段)
  • ng-脏了(用户在表单字段中输入了东西)

在与字段交互之后,错误消失了,新的类就出现了。

这又告诉我们什么呢?

而不是在页面加载时立即显示这些错误,我们可以在用户通过表单控件的toucheddirty状态与表单互动后才显示错误。

    <input type="text" placeholder="请输入用户名" formControlName="username" class="form-field-input" />  
    @if (signUpForm.get('username')?.invalid &&  
        (signUpForm.get('username')?.dirty || signUpForm.get('username')?.touched))  
    {  
      <p class="error-text">用户名必填项!</p>  
    }  

    <input type="password" placeholder="请输入密码" formControlName="password" class="form-field-input"/>  
    @if (signUpForm.get('password')?.invalid &&  
        (signUpForm.get('password')?.dirty || signUpForm.get('password')?.touched))  
    {  
      <p class="error-text">密码必填项!</p>  
    }

这会告诉 Angular 只在满足以下条件时显示该字段的错误:

  • 该字段无效了和
  • 要么被修改过,要么被输入过

我们也可以在那页上确认一下。

错误会在你点击该字段,然后移开鼠标(类从_ng-untouched_变成_ng-touched_)时出现,这正是我们所期待的。

要试试不同类型的数据验证

到目前为止,我们只讨论了必填项的情况。其他验证规则同样可以按这种方式验证,但在继续之前,我想先调整一下我们在代码中检查错误的方式。

迄今为止,我们从模板中获取控件并检查验证情况。我们可以通过将这些样板代码移到名为 getter 的函数中来改进这个过程。

    export class AppComponent implements OnInit {  

      signUpForm!: FormGroup;  

      constructor(private fb: FormBuilder) {}  

      ngOnInit(): void {  
        this.signUpForm = this.fb.group({  
          ...  
        });  
      }  

      // 获取用户名的输入框  
      get usernameControl(): AbstractControl {  
        return this.signUpForm.get('username') as AbstractControl;  
      }  

    }

_获取器_函数的作用是简化我们访问控制的方式。不再需要调用 this.signUpForm.get('username') 来检查 username 控制是否有效、是否被触或读取值等,我们只需调用 usernameControl 方法即可。

    <input type="text" placeholder="用户名" formControlName="username" class="form-field-input" />  

    @if (usernameControl.invalid && (usernameControl.dirty || usernameControl.touched))  
    {  
      <p class="error-text">请输入用户名!</p>  
    }

看起来好多了。现在,我们将使用 FormControlhasError() 方法来检查每个验证控件,我们在 Typescript 类中进行了这些设置:

  • Validators.required => usernameControl存在“required”错误
  • Validators.minLength(3) => usernameControl存在“最小长度”错误
  • Validators.maxLength(24) => usernameControl存在“最大长度”错误
    <input type="text" placeholder="用户名" formControlName="username" class="form-field-input" />  
    @if (usernameControl.invalid && (usernameControl.dirty || usernameControl.touched))  
    {  
       @if (usernameControl.hasError('required')) {  
         <p class="error-text">用户名是必填的!</p>  
       } @else if (usernameControl.hasError('maxlength')) {  
         <p class="error-text">用户名太长了哦!</p>  
       } @else {  
         <p class="error-text">用户名太短了哦!</p>  
       }  
    }

当控制正常时,错误就会消失。

这些getter方法也可以用在表单中的其他控件上。

    ngOnInit(): void {  
      this.注册表单 = this.fb.group({  
        ...  
      });  
    }   

    获取用户名控件(): AbstractControl {  
      return this.注册表单.get('username') as AbstractControl;  
    }  

    获取密码控件(): AbstractControl {  
      return this.注册表单.get('password') as AbstractControl;  
    }  

    获取年龄控件(): AbstractControl {  
      return this.注册表单.get('age') as AbstractControl;  
    }  

    获取记住我控件(): AbstractControl {  
      return this.注册表单.get('rememberMe') as AbstractControl;  
    }

年龄字段默认是可选的,因此这里不需要使用必填验证器。不过,我们可以检查最小值和模式验证器。

    <input type="text" placeholder="年龄" formControlName="age" class="form-field-input"/>
    @if (ageControl.invalid && (ageControl.dirty || ageControl.touched))
    {  
      @if (ageControl.hasError('min')) {  
        <p class="error-text">您必须年满12岁!</p>  
      } @else if (ageControl.hasError('pattern')) {  
        <p class="error-text">请输入数字!</p>  
      }  
    }

我故意将输入类型从“number”改成“text”,这样格式错误就会出现了。

异步验证功能

当验证表单数据与后端API时会应用异步验证功能。

为了让这个功能运作起来,我创建了一个基于Express.js的简单服务器。这个服务器提供了一个API,用于检查提供的用户名是否在现有用户列表中。

    const express = require('express');  
    const app = express();  
    const cors = require('cors');  

    app.use(express.json())  
    app.use(cors());  

    const users = ['Mystic', 'Phantom', 'Twingi', 'MornarPopaj'];  

    app.get('/api/user/:username', (req, res) => {  
      const { username } = req.params;  

      const isExistingUser = !!users.find(user => user === username);  

      res.status(200).send({ isExistingUser })  
    });  

    app.listen(3000, () => console.log('服务器启动了!'));

如果有匹配,API 会返回 true 或 false。否则的话,返回 false。

测试 API 的功能

Angular 服务模块

我们需要创建一个 Angular 服务来调用这个 API,比如调用下面的 API:

import { HttpClient } from '@angular/common/http';  
import { Injectable } from '@angular/core';  
import { Observable } from 'rxjs';  

// 检查用户是否存在的接口
export interface ICheckExistingUser {  
  isExistingUser: boolean;  
}  

// 依赖注入,提供在根服务中
@Injectable({  
  providedIn: 'root'  
})  
export class UsersService {  

  constructor(private http: HttpClient) {}  

  // 检查用户是否存在
  checkIfUserExists(username: string): Observable<ICheckExistingUser> {  
    return this.http.get<ICheckExistingUser>(`http://localhost:3000/api/user/${username}`);  
  }  
}
自定义验证规则:

下一步是创建一个自定义表单验证器来调用此服务。

    import { Injectable } from '@angular/core';  
    import { ICheckExistingUser, UsersService } from './features/core/services/users.service';  
    import {  
      AbstractControl,  
      AsyncValidatorFn,  
      ValidationErrors,  
    } from '@angular/forms';  
    import { Observable, catchError, map, of } from 'rxjs';  

    @Injectable({  
      providedIn: 'root',  
    })  
    export class UsersValidator {  
      constructor(private usersService: UsersService) {}  

      userExistsValidator(): AsyncValidatorFn {  
        return (control: AbstractControl): Observable<ValidationErrors | null> => {  
          if (!control.value) {  
            return of(null);  
            // 如果用户名输入框为空,则返回 null  
          }  

          return this.usersService  
          .checkIfUserExists(control.value)  
          .pipe(  
            map((data: ICheckExistingUser) =>   
              data.isExistingUser ? { isExistingUser: true } : null),  // 如果用户已存在  
            catchError(() => of(null))   
            // 发生错误时返回 null  
          );  
        };  
      }  
    }

这个验证器调用 API 并检查响应,如果响应为 true(表示用户名已存在),则返回 { isExistingUser: true }(表示已存在用户)。否则,返回 null(表示用户不存在)。

在组件中的自定义验证器

这里,我们将自定义验证器功能应用到用户名控件上:

    构造函数 (constructor)(
        private fb: FormBuilder,
        private readonly usersValidator: UsersValidator
      ) {}

      ngOnInit(): void {
        this.signUpForm = this.fb.group({
          username: [
            '',
            [Validators.required, Validators.minLength(3), Validators.maxLength(24)],
            [this.usersValidator.userExistsValidator()] // 异步验证器,检查用户是否存在
          ],
          password: ['', [Validators.required, Validators.minLength(10)]],
          age: ['', [Validators.min(12), Validators.pattern("^[0-9]*$")]], // 正则表达式验证输入是否为数字
          rememberMe: [true] // 默认值为true
        });
      }

然后,我们只需检查组件是否有 isExistingUser 错误(表示已存在用户)。

  • HTML模板
     <input type="text" placeholder="用户名" formControlName="username" class="form-field-input" />  
    @if (usernameControl.invalid && (usernameControl.dirty || usernameControl.touched))  
    {  
      @if (usernameControl.hasError('required')) {  
        <p class="error-text">用户名是必填的!</p>  
      } @else if (usernameControl.hasError('maxlength')) {  
        <p class="error-text">用户名太长了!</p>  
      } @else if (usernameControl.hasError('minlength')) {  
        <p class="error-text">用户名太短了!</p>  

        <!-- 异步验证 👇 -->  
      } @else if (usernameControl.hasError('isExistingUser')) {  
        <p class="error-text">用户名已被使用!</p>  
      }  
    }

使用可观察与响应式表单

这样使用异步验证器会有一点性能的影响——每次按键时都会调用一次 API。

天哪!
其实你可以这样来处理:按照这些规则。

  • 不要在用户停止输入之前调用 API,而是等待大约 300 毫秒。
  • 如果发出了新的搜索请求,取消现有的搜索请求。

这就是Rx.js Observables发挥作用的地方。
Angular中的响应式表单大量使用了Observables流。每个表单控件都是一个你可以操作的价值流(使用Rx.js操作符)。

valueChanges属性将表单控制的实时值变化转换为你可以订阅的可观察对象。

    import { debounceTime, distinctUntilChanged } from 'rxjs';  

    ngOnInit(): void {  
      this.signUpForm = this.fb.group({  
        username: ['', [Validators.required, Validators.minLength(3), Validators.maxLength(24)]],  
        password: ['', [Validators.required, Validators.minLength(10)]],  
        age: ['', [Validators.min(12), Validators.pattern("^[0-9]*$")]],  
        rememberMe: [true]  
      });  
    }  
    //  
    this.signUpForm.get('username')?.valueChanges  
      .pipe(  
         // 在用户停止输入500毫秒后再发出  
         debounceTime(500),  
         // 仅当值发生变化时才发出  
         distinctUntilChanged()  
      )  
      .subscribe((data: string) => {  
        console.log('data :>> ', data);  
      })  
    }
使用 Observables 来减少对 API 的调用

现在回到自定义验证器那里,应用限流策略。

    import { Observable, catchError, map, of, switchMap, timer } from 'rxjs';  

    @Injectable({  
      providedIn: 'root',  
    })  
    export class UsersValidator {  
      constructor(private usersService: UsersService) {}  

      userExistsValidator(): AsyncValidatorFn {  
        return (control: AbstractControl): Observable<ValidationErrors | null> => {  
          if (!control.value) {  
            return of(无);  
          }  

        // 开始一个300毫秒的计时器,在调用API之前等待300毫秒  
        return timer(300).pipe(  

          // 等待计时结束后调用API  
          switchMap(() => this.usersService.checkIfUserExists(control.value)),  

          // 检查是否有效  
          map((response: ICheckExistingUser) => (response.isExistingUser ? { 用户已存在: true } : 无)),  

          // 如果有错误则处理  
          catchError(() => of(无))  
        );  
        };  
      }  
    }

这样设置后,API调用会在用户停止输入后300毫秒会触发。

探索不同表单属性

这里有一些属性和方法,可以用来检查表单或其任何一个控件的状态,或更改它们的行为。

查看表单

读取表单值

this.signUpForm.value
  • 确认表单是否有效:
    this.signUpForm.valid // true / false

// 该代码行检查注册表单的有效性,返回 true 或 false。

  • 检查表单互动
this.signUpForm.status // 无效状态 / 有效状态  
this.signUpForm.dirty // 已修改 / 未修改  
this.signUpForm.touched // 已交互 / 未交互  
this.signUpForm.pristine // 未修改 / 未交互  
this.signUpForm.untouched // 未交互 / 未修改
  • 查找表单控件
    this.signUpForm.get('username') // Abstract Control  
    this.signUpForm.get('password') // Abstract Control
改变表现形式
  • 点击以清除表单中的值
    this.signUpForm.reset(); // 该语句用于重置 signUpForm 表单。

纠正错误。

    this.signUpForm.setErrors(null);
  • 标记为污损
this.signUpForm.markAsDirty(); // 这行代码标记了signUpForm为脏数据。
  • 标记为已处理
    this.signUpForm.markAsTouched();

// 这里标记表单已触碰

  • 更新有效期
    this.signUpForm.updateValueAndValidity();

使用相同的方法,你可以查看或修改某个控件。

    this.signUpForm.get('username')?.value;  
    this.signUpForm.get('username')?.valid;  
    this.signUpForm.get('username')?.touched;  
    this.signUpForm.get('username')?.dirty;  
    this.signUpForm.get('username')?.markAsDirty();  
    this.signUpForm.get('username')?.patchValue('新值') // 例如新值  
    this.signUpForm.get('username')?.setErrors(null) // 清除错误() 或者 设置错误(null)  
    this.signUpForm.get('username')?.hasError('required') // true / false 或者 false  
    // 等等...
收尾

Angular的响应式表单库提供了一种强大且直观的方式来创建和操作表单。这仅仅是冰山一角。在下一章,我们将深入探讨表单数组、自定义表单控件,以及如何用响应式表单和Angular Material搭配使用。

先聊了 👋

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP