FormBuilder组件已被弃用,建议使用验证器。

7

我遇到了与这里相似的问题:

如何解决使用自定义验证器语法时遇到的错误?

FormBuilder group已被弃用

我已经阅读过上述问题,但问题仍然出现在代码检查工具中:

group已弃用:此API不是类型安全的,可能会导致Closure Compiler重命名的问题。请改用带有AbstractControlOptions的 FormBuilder#group重载。注意,AbstractControlOptions期望validatorsasyncValidators为有效的验证器。如果您有自定义验证器,请确保它们的验证函数参数是AbstractControl,而不是子类,例如FormGroup。这些函数将使用AbstractControl类型的对象调用,无法自动向下转换为子类,因此TypeScript会将其视为错误。例如,将(group: FormGroup) => ValidationErrors|null签名更改为(group: AbstractControl) => ValidationErrors|null。(已弃用)

下面是我的formBuilder:

registerForm = this._fb.group({
        firstname: ["", [Validators.required]],
        lastname: ["", [Validators.required]],
        email: ["", [Validators.required, Validators.email]],
        password: ["", [PasswordValidator.strength]],
        confirmPassword: ["", [Validators.required]]
    }, {
        validator: PasswordValidator.confirmed("password", "confirmPassword")
    });

我的验证器:

export class PasswordValidator {
    static confirmed = (controlName: string, matchingControlName: string) => {
        return (formGroup: FormGroup) => {
            const control = formGroup.controls[controlName];
            const matchingControl = formGroup.controls[matchingControlName];

            if (matchingControl.errors && !matchingControl.errors.confirmedValidator) {
                return null;
            }

            if (control.value !== matchingControl.value) {
                matchingControl.setErrors({ confirmedValidator: true });
                return ({ confirmedValidator: true });
            } else {
                matchingControl.setErrors(null);
                return null;
            }
        };
    }
}

有什么想法吗?我正在返回正确的对象 :/。

我的意思是,错误是由于这一行 validator: PasswordValidator.confirmed("password", "confirmPassword") 引起的。 - Owen Kelvin
嗯,是的,我知道,但是,我该怎么解决呢? - DiPix
1
只需添加一个s... validators: [PasswordValidator.confirmed("password", "confirmPassword")] - Owen Kelvin
这并没有解决问题。虽然只有一个验证器。 - DiPix
即使只有一个或多个验证器,也必须使用带有“s”的validators,并将其传递给一个包含一个或多个项目的数组。 - Owen Kelvin
显示剩余5条评论
3个回答

12

@OwenKelvin部分正确。在formBuilder中,应该使用validators而不是validator,即使只有一个验证器,再次抱歉Owen。

但第二个问题出现在验证器中。该函数应接收AbstractControl而不是FormGroup。因此,以下代码是正确的:

export class PasswordValidator {
    static confirmed = (controlName: string, matchingControlName: string) => {
        return (control: AbstractControl): ValidationErrors | null => {
            const input = control.get(controlName);
            const matchingInput = control.get(matchingControlName);

            if (input === null || matchingInput === null) {
                return null;
            }

            if (matchingInput?.errors && !matchingInput.errors.confirmedValidator) {
                return null;
            }

            if (input.value !== matchingInput.value) {
                matchingInput.setErrors({ confirmedValidator: true });
                return ({ confirmedValidator: true });
            } else {
                matchingInput.setErrors(null);
                return null;
            }
        };
    }
}

我按照您的建议做了,但仍然遇到了完全相同的弃用错误。 - Un1xCr3w

4

对我来说,即使是链接的解决方案中提出的所有答案都没有起作用......这就是我的解决办法:

以下是验证器(包括自定义验证器)的调用方式:

 this.form = this.fb.group(
      {
      Password:                  ['', { validators:[ Validators.required, Validators.minLength(4)]}],
      ConfirmPassword:           ['', { validators:[ Validators.required, Validators.minLength(4)]}]
      },
      {validators: this.matchingPasswords('Password', 'ConfirmPassword')}
    )

这就是所谓的验证器(在本例中放置在同一组件中)。

matchingPasswords(Password: string, ConfirmPassword: string) {
    return (controls: AbstractControl) => {
      if (controls) {
        const Password = controls.get('Password')!.value;
        const ConfirmPassword = controls.get('ConfirmPassword')!.value;
        //console.log ("check what is passed to the validator", password, confirmPassword);
        if (Password !== ConfirmPassword) { 
          //this is an error set for a specific control which you can use in a mat-error
          controls.get('ConfirmPassword')?.setErrors({not_the_same: true});  
          //this is the returned error for the form normally used to disable a submit button
          return {mismatchedPassword: true}  
        }
      }
      return null;
    }
  }

   
  • 不需要(如我在一些线程中读到的)将验证功能放入单独的模块中。
  • 不需要将验证器调用声名为"AbstractControlOptions"(它反而会导致无法使用)。

需注意:

  1. 调用是对于验证器而不是单个验证函数。
  2. 值是通过.get提取的,需要使用!来确认我们确定它们不为null。
  3. 验证器必须返回ValidationError或null。

1
这是 Angular 12 的正确答案。 仅将“validator:”更改为“validators:”即可消除弃用消息。 - dEf

2
在哪里出现了错误?我用你的代码创建了一个stackblitz,但是我看不到错误。
顺便说一下,我不太喜欢使用setError来“放置”控件的错误。
如果您没有使用mat-error,您可以简单地询问form.errors。
如果您正在使用mat-error,则可以:
使用类似于自定义ErrorStateMatcher的方式,就像这个stackoverflow的示例一样。
或者创建一个验证器,通过考虑密码值来验证确认密码,例如这个stackoverflow的示例
或者使用bind(this)并查询this.registerForm.password,参见这个stackoverflow的示例

2
您的 StackBlitz 没有错误,因为您使用了“validators”。不幸的是,原帖作者坚持使用单数“validator”,因为他们只有一个验证器。 - Owen Kelvin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接