0
votes

"@angular/forms": "^4.4.6", "@angular/material": "^2.0.0-beta.12"

Trying to validate array of two fields in a form group comparing their range which should be between left side value and right and numeric. numeric is working but range check using custom validation error using mat-error message for that specific field is not displaying.

like

*ngIf="xxxDismissForm.get('xxx.value.1.value').hasError('betweenRangeIncorrect')"

is set as true/false based on custom validation condition and printing in template but the md-error field message is not displaying...

Is it a bug with mat-error or the hasError is set in inappropriate field i couldn't find. any help would be great

Html Template :

<div fxLayout="row">
          <mat-form-field formGroupName="0" class="m-t-7">
            <input [required]="xxxDismissForm.get('xxx.include').value === true" qa-name="eventIdValue1" formControlName="value"
              matInput type="number" placeholder="XXX" i18n-placeholder="XXX" (keypress)="validationService.checkIfProducesNumber($event)">
            <mat-error *ngIf="xxxDismissForm.get('xxx.value.0.value').hasError('pattern')" i18n="Field must be an integer error message">
              This field must be a positive integer
            </mat-error>
          </mat-form-field>

          <span class="event-id-connector">And</span>

          <mat-form-field formGroupName="1" class="m-t-7">
            <input [required]="autoDismissForm.get('xxx.include').value === true" qa-name="eventIdValue2" formControlName="value"
              matInput type="number" placeholder="XXX" i18n-placeholder="XXX" (keypress)="validationService.checkIfProducesNumber($event)">

      //This Mat-error works
            <mat-error *ngIf="xxxDismissForm.get('xxx.value.1.value').hasError('pattern')" i18n="Field must be an integer error message">
              This field must be a positive integer
            </mat-error>

      //This Mat-error not working but if is set as true/false based on condition         
    <mat-error *ngIf="xxxDismissForm.get('xxx.value.1.value').hasError('betweenRangeIncorrect')" i18n="left side of the range should be lower than the right side">
              Left side of the range should be lower than the right side
            </mat-error>


          </mat-form-field>
        </div>

My Form component :

xxxDismissForm = this.formBuilder.group({

xxx: this.formBuilder.group({
  include: [false],
  operator: [{ value: '', disabled: true }],
  value: this.formBuilder.array([
    this.formBuilder.group(
      { value: [{ value: null, disabled: true }, [Validators.pattern(Constants.Validation.ONLY_NUMBER_REGEX)]] }
    ),
    this.formBuilder.group(
      { value: [{ value: null, disabled: true }, Validators.pattern(Constants.Validation.ONLY_NUMBER_REGEX)] }
    )
  ])
}, {validator: FormValidationService.betweenValidator('value')}), 
// Validation is called but value is set true/ false but error message is not displayed
  });

Validation Service :

@Injectable()
export class FormValidationService {

static betweenValidator(controlName: string) {
return (group: FormGroup): { [key: string]: any } => {
  const control1 = group.controls[controlName].value[0];
  const control2 = group.controls[controlName].value[1];

  if (control1.value > control2.value) {
    group.controls[controlName].setErrors({'betweenRangeIncorrect': true});
    return {'betweenRangeIncorrect': true};
  }
  group.controls[controlName].setErrors(null);
  return null;
};
}
}
1

1 Answers

1
votes

This can be solved by a Custom Error State Matcher. By default, the mat-errors will only be shown if the actual form control is invalid. They do not take into account any validation on parent form groups.

Try this,

<input matInput formControlName="value" [errorStateMatcher]="groupErrorMatcher">

.

groupErrorMatcher = {
  isErrorState(control) => {
    // where xxx is the form group that has the comparison validator on it
    return (control.invalid || this.xxx.invalid) && (control.dirty || control.touched);
  }
}

Read more in the docs.