javascript - Kako koristiti ngIf na material inputu u child komponenti bez dobivanja ExpressionChangedAfterItHasBeenCheckedError


Problem

Imam PasswordComponent koji želim koristiti u ng-template. Međutim, sada dobivam pogrešku ExpressionChangedAfterItHasBeenCheckedError kada uređujem lozinku. Želim koristiti errorStateMatcher samo kada controlName === 'confirmPassword' i nisam uspio pronaći drugi način da uvjetno povežem errorMatcher

Cijeli kod možete vidjeti ovdje, a unutar password.component.html pronaći ćete ng-template koji uzrokuje problem:

  <template *ngIf="controlName === 'confirmPassword'; then Custom else Default"></template>
  <ng-template #Custom>
    <input matInput [placeholder]="placeholder" [formControlName]="controlName" [type]="showPassword ? 'text' : 'password'" [autocomplete]="autocomplete" [errorStateMatcher]="errorMatcher"/>
  </ng-template>
  <ng-template #Default>
    <input matInput [placeholder]="placeholder" [formControlName]="controlName" [type]="showPassword ? 'text' : 'password'" [autocomplete]="autocomplete"/>
  </ng-template>

Napomena: Čak i ako uklonite ng-template i stavite ngIf izravno na input, greška se i dalje pojavljuje. Isprva sam mislio da je problem u ng-template, ali zapravo je u ngIf.

Pogreška

Brojevi mat-error variraju i ponekad je vrijednost aria-describedby: null.

PasswordComponent.html:4 ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'aria-describedby: mat-error-3'. Current value: 'aria-describedby: mat-error-4'.

Koraci za reprodukciju pogreške

  • Unesite nešto u polje za lozinku
  • Pritisnite Tab/kliknite da se vratite na korisničko ime
  • Pritisnite Tab/kliknite natrag na lozinku
  • Upišite ili izbrišite znakove tako da se poruka mat-error promijeni
  • Vidjet ćete ExpressionChangedAfterItHasBeenCheckedError u konzoli.

Odgovor #1

Isprobajte sljedeće:

  <input #Custom *ngIf="controlName === 'confirmPassword'; else Default" matInput [placeholder]="placeholder" [formControlName]="controlName" [type]="showPassword ? 'text' : 'password'" [autocomplete]="autocomplete" [errorStateMatcher]="errorMatcher"/>

<ng-template #Default> 
        <input matInput [placeholder]="placeholder" [formControlName]="controlName" [type]="showPassword ? 'text' : 'password'" [autocomplete]="autocomplete"/> 
    </ng-template>

UREDI

Ukratko, vjerojatno je riječ o tome da dijete koristi vrijednost roditelja koja je promijenjena nakon što je dijete prikazano. To se obično događa jer se djeca prikazuju prije nego što roditelj završi s prikazivanjem. Isprva sam mislio da je problem u tome što ste direktivu errorStateMatcher stavili u predložak djeteta.

Pogledajte sljedeći članak jer objašnjava problem bolje nego što ja mogu i također prolazi kroz neke uobičajene obrasce koji uzrokuju problem i kako ih promijeniti da bi se riješio:

https://blog.angularindepth.com/sve-što-trebate-znati-o-gresci-expressionchangedafterithasbeenchecked-error-error-e3fd9ce7dbb4

UREDI

Slijedeći vaše komentare, moguće je da ngIf direktiva stvara sukob s matInput direktivom. Možete li pokušati sljedeće:

<ng-container *ngIf="controlName === 'confirmPassword'; else Default">
    <input #Custom matInput [placeholder]="placeholder" [formControlName]="controlName" [type]="showPassword ? 'text' : 'password'" [autocomplete]="autocomplete" [errorStateMatcher]="errorMatcher"/>
</ng-container>
<ng-template #Default> 
    <input matInput [placeholder]="placeholder" [formControlName]="controlName" [type]="showPassword ? 'text' : 'password'" [autocomplete]="autocomplete"/> 
</ng-template>

Sljedeće je radni primjer ovoga: StackBlitz primjer