控制更改时的角反应形式设置验证器

时间:2020-09-03 22:08:34

标签: angular validation angular-reactive-forms

我有一个反应形式,我想在更改密码值时更改密码确认密码 validators。我正在订购密码控制valueChanges,并在控制值更改时设置validators。为了避免只重复一次操作,我在设置validators后取消了订阅。

问题在于验证器设置正确,但是一旦完成所有字段的填写,尽管表格中没有错误,但将其标记为invalid

我尝试将validators之外的valueChanges设置为 this.form = this.fb.group({ usuario: [this.data.usuario, [Validators.required]], password: [this.data.password, [Validators.required, Validators.minLength(6)]], confirmarPassword: [{ value: '', disabled: true }], nombre: [this.data.nombre, [Validators.required]], apellido: [this.data.apellido, [Validators.required]], inicial: [this.data.inicial, [Validators.required]], email: [this.data.email, [Validators.required, Validators.email]], habilitado: [this.data.habilitado.value], imagenPerfil: [this.data.imagenPerfil, null], modoNuevoPerfil: [false], modoEditarPerfil: [false], permisos: this.fb.group({ nombre: ['', null], usuarios: this.fb.group({ alta: [false], baja: [false], modificacion: [false], visualizacion: [false] }), usuariosPerfiles: this.fb.group({ alta: [false], baja: [false], modificacion: [false], visualizacion: [false] }), configuracionesTecnicas: this.fb.group({ alta: [false], baja: [false], modificacion: [false], visualizacion: [false] }), drogas: this.fb.group({ alta: [false], baja: [false], modificacion: [false], visualizacion: [false] }), drogasCertificados: this.fb.group({ alta: [false], baja: [false], visualizacion: [false] }), drogasRetesteos: this.fb.group({ alta: [false], baja: [false], modificacion: [false], aprobarRechazar: [false], visualizacion: [false] }), drogasMovimientos: this.fb.group({ alta: [false], baja: [false], modificacion: [false], visualizacion: [false] }), soluciones: this.fb.group({ alta: [false], baja: [false], modificacion: [false], aprobarRechazar: [false], visualizacion: [false] }), equiposAuxiliares: this.fb.group({ alta: [false], baja: [false], modificacion: [false], visualizacion: [false] }), equiposAuxiliaresCertificados: this.fb.group({ alta: [false], baja: [false], modificacion: [false], visualizacion: [false] }), materialVolumetrico: this.fb.group({ alta: [false], baja: [false], modificacion: [false], visualizacion: [false] }), materialVolumetricoCertificados: this.fb.group({ alta: [false], baja: [false], modificacion: [false], visualizacion: [false] }), }) }); ,它可以正常工作。

我尝试使用一个函数来返回有错误的控件,但是一旦按预期完成所有字段,就不会返回错误。

我不知道为什么它不能正常工作。

表单代码:

this.passwordChange$ = this.form.controls.usuario.valueChanges.subscribe(
    () => {
        this.form.setValidators(this.passwordCoinciden('password', 'confirmarPassword'));
        this.form.controls.confirmarPassword.enable()
        this.form.controls.confirmarPassword.setValidators([Validators.required]);
        this.form.updateValueAndValidity()
        this.passwordChange$.unsubscribe()
    }
)

值更改订阅代码:

 function findInvalidControls() {
     const invalid = [];
     const controls = this.form.controls;
     for (const name in controls) {
         if (controls[name].invalid) {
             invalid.push(name);
         }
     }
     return invalid;
 }

检查错误代码的功能:

{{1}}

3 个答案:

答案 0 :(得分:0)

我写了一篇有关RF和自定义验证器功能的文章,您可以找到一些示例

https://dev.to/salimchemes/reactiveforms-formarrays-and-custom-validators-1d0k

答案 1 :(得分:0)

我已经找到一种解决此问题的方法,我不明白为什么它如此有效,但仍然可以帮助某些人。

在初始化表单时设置我的cumstom验证器,但请禁用我的confirmarPassword,以便不检查验证。

然后我订阅this.form.controls.password.valueChanges,当它更改时,我启用confirmarPassword

因此,正如我所说,我不知道为什么,但是如果将表单验证器设置在formControl valueChanges可见的范围内,表单验证器将无法正常工作。

表单代码:

         this.form = this.fb.group({
         usuario: [this.data.usuario, [Validators.required]],
         password: [this.data.password, [Validators.required, Validators.minLength(6)]],
         confirmarPassword: [{ value: '', disabled: true }],
         nombre: [this.data.nombre, [Validators.required]],
         apellido: [this.data.apellido, [Validators.required]],
         inicial: [this.data.inicial, [Validators.required]],
         email: [this.data.email, [Validators.required, Validators.email]],
         habilitado: [this.data.habilitado.value],
         imagenPerfil: [this.data.imagenPerfil, null],
         modoNuevoPerfil: [false],
         modoEditarPerfil: [false],
     });
// Here I set the validator but it does not work until I enable 'confirmarPassword'
    this.form.setValidators(this.passwordCoinciden('password', 'confirmarPassword'));

价值更改订阅代码:

this.passwordChange$ = this.form.controls.usuario.valueChanges.subscribe(
    () => {
        this.form.controls.confirmarPassword.setValidators([Validators.required]);
        this.form.controls.confirmarPassword.enable()
        this.form.updateValueAndValidity()
        this.passwordChange$.unsubscribe();
    }
)

UPDATE 9/7/2020

我发现问题出在我的自定义验证器中,我没有正确使用ValidatorFn接口,因为在没有错误而不是null的情况下,我返回的是空对象。

修改后的定制验证码

passwordCoinciden(_password: string, _confirmarPassword: string) : ValidatorFn{
return (group: FormGroup): {[key: string]: any} => {
  let password = group.controls[_password];
  let confirmarPassword = group.controls[_confirmarPassword];

  if (password.value && confirmarPassword.value && password.value != confirmarPassword.value ) {
    this.form.controls[_confirmarPassword].markAllAsTouched()
    this.form.controls[_confirmarPassword].setErrors({passNoCoinciden: "Los passwords no coinciden" })
    return {passNoCoinciden: "Los passwords no coinciden" }
           
  } else {
  this.form.controls[_confirmarPassword].setErrors(null);
   return  null
  } 
}

}

答案 2 :(得分:0)

这是一个工作示例。

export class AppComponent implements OnInit {
  loginForm: FormGroup = this.fb.group({
    phonenumber: [""],
    check: [false]
  });

  constructor(private fb: FormBuilder) {}

  ngOnInit() {
    this.loginForm.get("check").valueChanges.subscribe(value => {
      if (value) {
        this.loginForm.get("phonenumber").setValidators([Validators.required]);
      } else {
        this.loginForm.get("phonenumber").clearValidators();
      }
      this.loginForm.get("phonenumber").updateValueAndValidity({ emitEvent : false });
      console.log(this.loginForm.valid);
    });
  }

  loginUser() {}
}

你可以测试一下here

对于那些收到“MaxExecutionStack...”错误的人,请注意,这是因为

emitEvent : false

updateValueAndValidity 方法中的选项!