javascript - 如何在不获取 ExpressionChangedAfterItHasBeenCheckedError 的情况下对子组件中的 Material 输入使用 ngIf

标签 javascript angular typescript angular-material

问题

我有一个 PasswordComponent,我想在其中使用 ng-template。但是,我现在遇到 ExpressionChangedAfterItHasBeenCheckedError 错误m 编辑密码。我只想在 controlName === 'confirmPassword' 时使用 errorStateMatcher 并且我想不出另一种方法来有条件地绑定(bind) errorMatcher

完整代码可见herepassword.component.html 中,您会找到导致问题的 ng-template:

  <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>

Note: Even if you remove the ng-template and put the ngIf on the input directly the error still shows. I originally thought the problem to be with the ng-template, but it's actually the ngIf.

错误

mat-error 数字各不相同,有时值为 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'.

错误重现步骤

  • 在密码字段中输入内容
  • Tab/点击回到用户名
  • Tab/点击返回密码
  • 键入或删除字符,使 mat-error 消息发生变化
  • 您将在控制台中看到 ExpressionChangedAfterItHasBeenCheckedError

最佳答案

尝试以下操作:

  <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>

编辑

简而言之,它可能归结为使用在呈现子项后已修改的父值的子模板。这通常发生在父级完成渲染之前渲染子级。我最初认为这是因为您将 errorStateMatcher 指令放在了子模板中。

看看下面的文章,它比我更好地解释了这个问题,并且还介绍了导致问题的一些常见模式以及如何更改它们以解决问题:

https://blog.angularindepth.com/everything-you-need-to-know-about-the-expressionchangedafterithasbeencheckederror-error-e3fd9ce7dbb4

编辑

根据您的评论,可能是 ngIf 指令与 matInput 指令冲突。您可以尝试以下操作吗:

<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>

以下是一个工作示例:StackBlitz Example

关于javascript - 如何在不获取 ExpressionChangedAfterItHasBeenCheckedError 的情况下对子组件中的 Material 输入使用 ngIf,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54895316/

相关文章:

javascript - 如何在 Angular 中添加动态外部脚本?

javascript - 使用 KnockoutJS,在 foreach 中呈现后如何滚动到组件?

加载另一个页面后 JavaScript 停止工作

javascript - 将嵌套的 JSON 数据映射到 Knockout observableArray

javascript - 在 JS 中生成非常长的字符串(数十兆字节)的最有效方法

Angular 构建错误 "..has no exported member ' ɵReflectorReader'。”

javascript - 在客户端系统中使用客户端脚本的文件下载选项

javascript - AngularJS Web 应用程序仅在 Chrome 70 上中断

angular - 未处理的 promise 拒绝 : Zone. js 检测到 ZoneAwarePromise : Angular

javascript - Jest mock winston 记录器