You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确使用Angular表单校验?实现字段校验与错误视觉反馈

组件代码(component.ts)修改

  1. 为表单控件添加 getter 时使用非空断言!,明确告知 TypeScript 该控件必然存在,解决"object is possibly null"报错
  2. 提交函数新增前置校验,表单无效时直接阻止提交并触发所有控件的错误状态
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { AuthService } from 'src/app/services/auth.service';
import { Router } from '@angular/router';

@Component({
  selector: 'app-register',
  templateUrl: './register.component.html',
  styleUrls: ['./register.component.scss']
})
export class RegisterComponent implements OnInit {
  // 加非空断言,确认ngOnInit一定会初始化该表单
  form!: FormGroup;
  error: string = '';

  constructor(private auth: AuthService, private router: Router) { }

  // 新增表单控件getter
  get name() {
    return this.form.get('name')!;
  }
  get email() {
    return this.form.get('email')!;
  }
  get password() {
    return this.form.get('password')!;
  }

  ngOnInit(): void {
    this.form = new FormGroup({
      name: new FormControl('', [Validators.required]),
      email: new FormControl('', [
        Validators.required,
        Validators.pattern("^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,4}$")
      ]),
      password: new FormControl('', [
        Validators.required,
        Validators.minLength(8)
      ])
    })
  }

  submit(){
    // 新增前置校验
    if (this.form.invalid) {
      // 标记所有控件为已触碰,触发错误样式
      this.form.markAllAsTouched();
      return;
    }
    this.auth.tryRegister(this.form.getRawValue())
    .subscribe(
      res => {
        if(res.status == 200){
          this.router.navigate(['/verify'])
        }},
      err => {
        if(err.status == 400){
          this.error = 'Invalid form data'
        } else if(err.status == 401){
          this.error = 'email address already in use'
        }
      })
  }
}

模板代码修改

  1. 给form标签添加模板引用变量#regForm="ngForm"获取表单提交状态
  2. 给每个input绑定动态类,满足「非法+已修改/已触碰/表单已提交」条件时,添加自定义的is-invalid类
  3. 可选添加对应错误提示文本
<div class="content">
    <section>
        <div class="form-wrapper">
            <h3>Registrieren</h3>
            <form class="form" [formGroup]="form" (submit)="submit()" #regForm="ngForm">
                <div class="form-item">
                    <input 
                      type="text" 
                      formControlName="name" 
                      placeholder="Name"
                      [ngClass]="{'is-invalid': name.invalid && (name.dirty || name.touched || regForm.submitted)}"
                    >
                    <!-- 可选错误提示 -->
                    <span *ngIf="name.invalid && (name.dirty || name.touched || regForm.submitted)" class="error-text">
                      请输入姓名
                    </span>
                </div>
                <div class="form-item">
                    <input 
                      formControlName="email" 
                      type="email" 
                      placeholder="Email Addresse"
                      [ngClass]="{'is-invalid': email.invalid && (email.dirty || email.touched || regForm.submitted)}"
                    >
                    <!-- 分类型错误提示 -->
                    <span *ngIf="email.errors?.['required'] && (email.dirty || email.touched || regForm.submitted)" class="error-text">
                      请输入邮箱
                    </span>
                    <span *ngIf="email.errors?.['pattern'] && (email.dirty || email.touched || regForm.submitted)" class="error-text">
                      请输入合法的邮箱地址
                    </span>
                </div>
                <div class="form-item">
                    <input 
                      formControlName="password" 
                      type="password" 
                      placeholder="Passwort"
                      [ngClass]="{'is-invalid': password.invalid && (password.dirty || password.touched || regForm.submitted)}"
                    >
                    <span *ngIf="password.errors?.['required'] && (password.dirty || password.touched || regForm.submitted)" class="error-text">
                      请输入密码
                    </span>
                    <span *ngIf="password.errors?.['minlength'] && (password.dirty || password.touched || regForm.submitted)" class="error-text">
                      密码长度不能少于8位
                    </span>
                </div>
                <div class="form-item">
                    <button type="submit">Registrieren</button>
                </div>
            </form>
        </div>
    </section>
</div>

样式补充

在组件的scss文件中添加对应样式即可:

.is-invalid {
  border: 1px solid #f5222d;
}
.error-text {
  color: #f5222d;
  font-size: 12px;
  margin-top: 4px;
  display: block;
}

如果你不想使用自定义类,也可以直接对Angular内置的状态类写样式,Angular会自动给非法的已修改/已触碰控件添加ng-invalid、ng-dirty、ng-touched类,直接对这些类设置样式即可实现相同效果。

内容的提问来源于stack exchange,提问作者Kleecarim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 20:48:03