0

"@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 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.