Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Issue with formGroup.hasError not returning true when custom validator returns error object

My angular 2 application uses reactive forms.

I initialize the following FormGroup in one of my components:

  ngOnInit() {
    ...

    this.addressForm = this.formBuilder.group({
      address: this.formBuilder.control({
        placeId: this.address.placeId,
        description: this.address.description
      }, addressValidator)
    });
  }

Here is the definition for the addressValidator:

import {AbstractControl} from '@angular/forms';

export function addressValidator(control: AbstractControl) {

  const {placeId} = control.value;

  return (placeId !== undefined && placeId !== null && placeId !== '') ? null : {addressValidator: {emptyPlaceId: true}};
}

Here is how I try to check whether the form control i.e. address is in error:

  addressFormErrors(error: string) {
    return this.addressForm.hasError(error, ['address', 'addressValidator']);
  }

Here is the template calling the addressFormErrors method:

<form [formGroup]="addressForm" (ngSubmit)="updateAddress()" novalidate>
  <div class="form-group" [ngClass]="getFeedbackClasses(addressForm, 'address', submitted)">
    <div class="input-group">
      <input type="text"
         formControlName="address"
         placeholder="{{'ADDRESS_FORM.NEW_ADDRESS' | translate}}"
         [ngbTypeahead]="chooseAddress"
         [inputFormatter]="addressFormatter"
         [resultFormatter]="addressFormatter"
         autocomplete="off"
         class="form-control"
         [ngClass]="formControlStatusClass(addressForm, 'address', submitted)">
    </div>
    <div [hidden]="addressForm.valid || !submitted">
      <div *ngIf="addressFormErrors('emptyPlaceId')" class="form-control-feedback form-control-label">{{'ADDRESS_FORM.ADDRESS_REQUIRED' | translate}}</div>
    </div>
  </div>
  ...
</form>

Here is the method invoked upon form submission:

  updateAddress() {
    this.submitted = true;
    if (this.addressForm.valid) {
      const placeId = this.addressForm.controls['address'].value['placeId'];
      this.userAccountService.updateAddress(placeId)
        .subscribe(() => this.router.navigate(['/dashboard/useraccount']));
    }
  }

edit: Gunter is right: the validator does indeed return the error object on value change. The issue is elsewhere: it is in the addressFormErrors method not returning true - probably due to some mistake in the property path specification.

Can someone please help?

like image 202
balteo Avatar asked Jan 07 '17 20:01

balteo


People also ask

How do you add validation in reactive form?

Adding async validators to reactive formslink To use an async validator in reactive forms, begin by injecting the validator into the constructor of the component class. Then, pass the validator function directly to the FormControl to apply it.

Why is my form validation not returning true?

The issue is elsewhere: it is in the addressFormErrors method not returning true - probably due to some mistake in the property path specification. Can someone please help? Validators are supposed to be executed when the values change, not on submit. You're right Günter.

What is a custom form validator?

Let's now quickly summarize everything that we have learned about custom form validators: a custom validator is a function that validates the value of a form field according to a business rule, such as form example the field is mandatory or the password needs to have a certain strength

Does the validator return the Error Object on value change?

edit: Gunter is right: the validator does indeed return the error object on value change. The issue is elsewhere: it is in the addressFormErrors method not returning true - probably due to some mistake in the property path specification. Can someone please help? Validators are supposed to be executed when the values change, not on submit.

Why are errors not displayed when using a custom validator directive?

When using a custom validator directive with FormGroup and mat-error, errors are not displayed and behavior is unpredictable. Moving between fields may display one or more errors, some are duplicated. Other fields not in the FormGroup are also affected.


1 Answers

Changing the returned error object from

{addressValidator: {emptyPlaceId: true}}

to:

{emptyPlaceId: true}

and the addressFormErrors from

  addressFormErrors(error: string) {
    return this.addressForm.hasError(error, ['address', 'addressValidator']);
  }

to:

  addressFormErrors(error: string) {
    return this.addressForm.controls['address'].hasError(error);
  }

fixed it.

However, please note that this not an altogether satisfactory solution as I am no longer able to specify different error types on the same validator.

I would be grateful if someone could explain how to properly use the hasError method with custom validators.

like image 153
balteo Avatar answered Sep 28 '22 07:09

balteo