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

Angular FormBuilder group弃用:自定义验证器报错求助

Angular自定义验证器报错修复方案

问题1:FormBuilder.group配置属性名错误

你在创建FormGroup时,配置对象里写的是Validators: this.validatorService.camposIguales('password','password2'),但Angular的AbstractControlOptions要求属性名是小写的validators。大写的Validators会被当成普通自定义属性,导致Angular识别不到你要设置的表单级验证器,进而触发"API类型不安全"的报错。

问题2:单个控件验证器的参数类型不符合要求

你的noPuedesSerYo验证器参数类型是FormControl,但报错提示明确要求验证器参数必须是AbstractControl类型(不能用子类),因为Angular调用验证器时传入的是AbstractControl实例,无法自动向下转换为子类,这会导致类型安全问题和Closure Compiler重命名问题。


修改后的代码

1. ValidatorService修改

import { Injectable } from '@angular/core';
import { AbstractControl, ValidationErrors } from '@angular/forms';

@Injectable({
  providedIn: 'root'
})
export class ValidatorService {

  public nombreApellidoPattern:string = '([a-zA-Z]+) (.+[a-zA-Z])';
  public emailPattern: string = "^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,4}$";

  constructor() { }

  // 将参数类型从FormControl改为AbstractControl
  noPuedesSerYo (control: AbstractControl): ValidationErrors | null {
    const valor:string = control.value?.trim().toLowerCase();
    if(valor === 'pepepepon'){
      return {noYo:true};
    }
    return null;
  }

  camposIguales(campo1:string, campo2:string){
    return (control: AbstractControl)=>{
      const pass1 = control.get(campo1)?.value;
      const pass2 = control.get(campo2)?.value;

      if(pass1 !== pass2){  
        return {noIguales:true};
      }

      // 建议不要手动设置子控件errors,避免覆盖其他验证错误
      // control.get(campo2)?.setErrors(null);
      return null;
    }
  }

}

2. 组件代码修改

import { Component, OnInit } from '@angular/core';
import {FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ValidatorService } from 'src/app/shared/validator/validator.service';

@Component({
  selector: 'app-registro',
  templateUrl: './registro.component.html',
  styleUrls: ['./registro.component.css']
})
export class RegistroComponent implements OnInit {

  miFormulario:FormGroup = this.fb.group({
    nombre:['',[Validators.required, Validators.pattern(this.validatorService.nombreApellidoPattern)]],
    email:['',[Validators.required, Validators.pattern(this.validatorService.emailPattern)]],
    username:['',[Validators.required, this.validatorService.noPuedesSerYo]],
    password:['',[Validators.required,Validators.minLength(6)]],
    password2:['',[Validators.required]]
  },{
    // 把Validators改成小写的validators
    validators: this.validatorService.camposIguales('password','password2')
  });

  constructor(private fb:FormBuilder, private validatorService:ValidatorService){}

  ngOnInit(): void {
    this.miFormulario.reset({
      nombre:'',
      email:'',
      username:'',
      password:'',
      password2:''
    })
  }

  campoInvalido(campo:string){
    return this.miFormulario.get(campo)?.invalid && this.miFormulario.get(campo)?.touched;
  }

  submitForm(){
    this.miFormulario.markAllAsTouched();
  }

}

额外优化建议

在camposIguales验证器里,不要手动调用control.get(campo2)?.setErrors(null),因为这会清除password2控件的其他验证错误(比如required)。表单级验证器只需要返回对应的错误对象即可,Angular会自动管理控件的错误状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 10:40:17