balteo
balteo

Reputation: 24709

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?

Upvotes: 5

Views: 14521

Answers (1)

balteo
balteo

Reputation: 24709

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.

Upvotes: 7

Related Questions