JMan
JMan

Reputation: 2629

Angular *ngIf not updated with component method

When using a function to show/hide with *ngIf the block is not updated in the html. when rendering the block to check the value ({{contactInfoValid(contact)}}) it is updated correctly, the *ngIf is not being triggered

HTML

<mat-form-field>
            <input matInput  type="text"
                      [(ngModel)]="contact.info" required>               
            <mat-error *ngIf="contactInfoValid(contact) == false">
               email not correct
            </mat-error>
        </mat-form-field>

Component

  contactInfoValid(contact) {
    if (contact.hasValidInfo) {
       return true;
       }

    return false;
  }

The mat-error is never shown.

A FormControl cannot be used in this specific case since it is used in a dynamic grid

Upvotes: 1

Views: 764

Answers (2)

Radik
Radik

Reputation: 2795

it could be by design as described here

workaround is add FormControl like this instaed of binding to [(ngModel)]

email = new FormControl('', [Validators.required, Validators.email]);

<div class="example-container">
  <mat-form-field appearance="fill">
    <mat-label>Enter your email</mat-label>
    <input matInput placeholder="[email protected]" [formControl]="email" required>
    <mat-error *ngIf="email.invalid">{{getErrorMessage()}}</mat-error>
  </mat-form-field>
</div>

Upvotes: 0

DaggeJ
DaggeJ

Reputation: 2191

The <mat-error> component need an ErrorStateMatcher in order to display anything. There's a good article about this here; https://itnext.io/materror-cross-field-validators-in-angular-material-7-97053b2ed0cf

In short you need to specify [errorStateMatcher]="myErrorStateMatcher" on the form field that you're validating.

<mat-form-field>
   <input matInput type="text" [(ngModel)]="contact.info" required
        [errorStateMatcher]="myErrorStateMatcher">
   <mat-error *ngIf="contactInfoValid(contact) == false">
       email not correct
   </mat-error>
</mat-form-field>

Normally ErrorStateMatcher works with FormControls, but if you want to use ngModel you can provide custom ErrorStateMatcher that have access to the data you need in order to display error messages. Below is a simplified example of this;

export class RuleErrorStateMatcher<T> implements ErrorStateMatcher {
    constructor(private editControl: IValidatableEditControl<T>) { }

    isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
        return this.editControl && this.editControl.model && !this.editControl.model.isValid;
    }
}

export interface IValidatableEditControl<T> {
    model: ValidationGeneric<T>;
}

export class ValidationGeneric<T>   {
    public value: T;
    public isValid: boolean;
}

If you try another html tag than mat-error you will see that your ngIf is probably working;

<span *ngIf="contactInfoValid(contact) == false">
        email not correct
</span>

Upvotes: 1

Related Questions