Angular 2 custom validator to check when either one of the two fields is required

一笑奈何 提交于 2019-12-21 04:43:25

问题


I am trying to implement a custom validator function to check either of the Phone numbers(Home Phone and Mobile) are entered or not. I want to show the error message on both the fields when they are both touched and not have the valid value, for some reason my code is not working as anticipated. Please help me with this piece. -Thanks! Here is the stackblitz link https://stackblitz.com/edit/angular-ve5ctu

createFormGroup() {
   this.myForm = this.fb.group({
     mobile : new FormControl('', [this.atLeastOnePhoneRequired]),
     homePhone : new FormControl('', [this.atLeastOnePhoneRequired])
   });
}

atLeastOnePhoneRequired(control : AbstractControl) : {[s:string ]: boolean} {
  const group = control.parent;
  if (group) {
    if(group.controls['mobile'].value || group.controls['homePhone'].value) {
      return;
    }
  }
  let errorObj = {'error': false};
  return errorObj;
}

回答1:


Instead of marking the validator on each formControl, make a nested group for the phone numbers and apply the validator to that group. In this sample I'll just apply the validator on the whole form.

Also when applying validators we need to return null when the field is valid.

Also, since you are using Angular material, we need to add a ErrorStateMatcher to be able to show mat-errors. mat-errors show only when validators are set to form control, not a formgroup.

Your code should look like follows:

createFormGroup() {
  this.myForm = this.fb.group({
    mobile : new FormControl(''),
    homePhone : new FormControl('')
      // our custom validator
  }, { validator: this.atLeastOnePhoneRequired});
}

atLeastOnePhoneRequired(group : FormGroup) : {[s:string ]: boolean} {
  if (group) {
    if(group.controls['mobile'].value || group.controls['homePhone'].value) {
      return null;
    }
  }
  return {'error': true};
}

The error state matcher:

export class MyErrorStateMatcher implements ErrorStateMatcher {
  isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
    const controlTouched = !!(control && (control.dirty || control.touched));
    const controlInvalid = !!(control && control.invalid);
    const parentInvalid = !!(control && control.parent && control.parent.invalid && (control.parent.dirty || control.parent.touched));

    return (controlTouched && (controlInvalid || parentInvalid));
  }
}

which you mark in component with:

matcher = new MyErrorStateMatcher();

and then mark it to your template on both input fields. Also note how the *ngIf looks for displaying validation messages:

<mat-form-field>
  <input matInput placeholder="Mobile" formControlName="mobile" [errorStateMatcher]="matcher">
  <mat-error *ngIf="myForm.hasError('error')">
    "Enter either phone number"
  </mat-error>
</mat-form-field>
<mat-form-field>
  <input matInput placeholder="Home Phone" formControlName="homePhone" [errorStateMatcher]="matcher">
  <mat-error *ngIf="myForm.hasError('error')">
    "Enter either phone number"
  </mat-error>
</mat-form-field>

StackBlitz



来源:https://stackoverflow.com/questions/47661680/angular-2-custom-validator-to-check-when-either-one-of-the-two-fields-is-require

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!