Angular 5:Reactive Forms - 更新表单控件时表单组验证重新触发

时间:2018-04-11 04:16:06

标签: angular custom-validators

我正在使用Angular 5 Reactive forms,并设置form groupconfirmEmail,其中两个form controlsemailconfirmEmail。我进一步向validator添加了form group,并form controls附加了required次验证。

My use case is:我想根据各个表单控件的值触发custom validation,如果自定义验证程序返回为invalid,请将表单控件标记为有错误。< / p>

My issue is thatform controls标记有错误后,自定义验证程序(在表单组上)不再触发,直到我再次触摸两个表单控件并更改它们的值。 理想情况下,我希望只更新其中一个字段(以匹配另一个字段)并能够再次触发自定义验证。

示例代码:

@Component({...})
export class FormComponent implements OnInit {
  user: FormGroup;
  constructor(private fb: FormBuilder) {}
  ngOnInit() {
    this.user = this.fb.group({
      data: this.fb.group({
        email: ['', Validators.required],
        confirmEmail: ['', Validators.required]
      }, , { validator: validateEmail })
    });
  }

  const validateEmail = (control: AbstractControl): {[key: string]: boolean} => {
    const email = control.get('email');
    const confirmEmail = control.get('confirmEmail');

    if (email.value === confirmEmail.value) {
          return null;
     } else {
       this.setFieldAsInvalid(email);
       this.setFieldAsInvalid(confirmEmail);
       return { nomatch: true };
     }
  };

  private setFieldAsInvalid(field: AbstractControl) {
      field.setErrors({
        'invalid': true
      });
   }
}

有任何建议可以解决这个或我应采取的任何其他方法。

2 个答案:

答案 0 :(得分:0)

当控件(email和confirmEmail)保持不同的值时,你将它们更改为无效, return null在ValidatorFun中只会将当前的formcontrol的有效值更改为true,并非所有电子邮件和确认电子邮件

<强>解决方法1: 您可以更改电子邮件,并在保持相同值时通过field.setErrors(null)确认电子邮件返回有效

if (email.value === confirmEmail.value) {
  // clear custom error for all related controls
  this.setFieldAsValid(email);
  this.setFieldAsValid(confirmEmail);
  return null;
} else {
  this.setFieldAsInvalid(email);
  this.setFieldAsInvalid(confirmEmail);
  return { nomatch: true };
}


private setFieldAsValid(field: AbstractControl) {
  field.setErrors(null);
}

查看已修复的 demo

<强>溶液2: 如果您只关心错误nomatch,则可以跟踪表单组data,看看它是否有nomatch错误,如下所示(也包含在上面的演示模板中部分):

this.user.get('data').hasError('nomatch')     

提到这种方式会使另一个formcontrol无效。

答案 1 :(得分:0)

我使用反应式方法创建了一个示例表单,其中我使用了内置验证器和自定义验证器。

打字稿:

export class AppComponent  {

  forbiddenEmails = ['test@test.com'];

  loginForm = new FormGroup({
    'name': new FormControl(null, [Validators.required]),
    'email': new FormControl(null, [Validators.required, Validators.email, this.customEmailValidator.bind(this)])
  });

  onSubmit(){
    console.log(this.loginForm.get('email').value);
  }

  customEmailValidator(control: FormControl): {[params: string]: boolean}{
    console.log(this.forbiddenEmails.indexOf(control.value));
    if(this.forbiddenEmails.indexOf(control.value) === 0){
      return {'forbiddenEmail': true};
    }else{
       return null;
    }
  }
}

模板:

   <h3>Basic Form</h3>
    <form class="form-horizontal"  [formGroup]='loginForm' (ngSubmit)="onSubmit()">
        <div class="form-group">
            <label for="name" class="col-sm-3 control-label">Name:</label>
            <div class="col-sm-6">
                <input type="text" 
                id="name" 
                class="form-control"
                formControlName='name' />
            </div>
            <div class="col-sm-3"></div>
            <span *ngIf='loginForm.get("name").invalid && loginForm.get("name").touched'>Pleas enter a valid name !!!</span>
        </div>
        <div class="form-group">
            <label for="email" class="col-sm-3 control-label">Email:</label>
            <div class="col-sm-6">
                <input type="email"
                 id="email"
                 class="form-control"
                 formControlName="email"/>
            </div>
            <div class="col-sm-3"></div>
            <span *ngIf='loginForm.get("email").invalid && loginForm.get("email").touched'>Pleas enter a valid email !!!</span>
        </div>
        <hr>
        <button class="btn btn-primary" 
        type="submit"
        [disabled]='!loginForm.valid'
        >Submit</button>
    </form>

链接:https://stackblitz.com/edit/angular-nwahpa?file=app%2Fapp.component.html