ExpressionChangedAfterItHasBeenCheckedError:表达式在检查后已更改。以前的值:“未定义”异常

Posted

技术标签:

【中文标题】ExpressionChangedAfterItHasBeenCheckedError:表达式在检查后已更改。以前的值:“未定义”异常【英文标题】:ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'undefined' Exception 【发布时间】:2020-06-16 09:01:54 【问题描述】:

我知道这个问题已经被问过很多次了,但是在阅读了类似的问题之后,我仍然无法组织我的代码来修复这个异常,

在我的组件中,我有这个根据条件动态变化的属性

public emailToValue: string

在我的html

用户可以手动添加一个新行,然后我调用一个管道来设置组件中分配的值

<ng-container matColumnDef="emailTo">
<mat-header-cell *matHeaderCellDef mat-sort-header>Email To</mat-header-cell>
<mat-cell *matCellDef="let userMarket">
 userMarket | formatEmailTo : emailToValue
<input type="text"  matInput [value]="userMarket.emailTo">
</mat-cell>
</ng-container>

这是我的管道,如果电子邮件为 null 或未定义,我默认设置一个电子邮件以显示在新行中

  @Pipe(
  name: 'formatEmailTo',
)
export class FormatEmailPipe implements PipeTransform 
  public transform(userMarket: UserMarketDTO, email: string): void 
    if (_.isNil(userMarket.emailTo)) 
    userMarket.emailTo = email;
    
  

功能正常,但每次创建新行时都会出现此异常

ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'value: undefined'. Current value: 'value: suport@support.com'.

我会很感激任何帮助

谢谢

【问题讨论】:

【参考方案1】:

这里有几点:

    功能仅在更改检测运行两次的开发模式下工作。当您收到该错误时,这意味着 undefined 的第一个值将是生产中前端的值。 我不确定这是管道的最佳用途。我通常希望管道能够实际转换并返回 HTML 需要的值。对我来说,听起来您应该在添加行时默认您的电子邮件值。

但假设有一些要求迫使您这样做,并且您想避免使用 ChangeDetectorRef,我想我有一个解决方案给您。请看我的stackblitz:

使用template ref 用于已通过管道传输的UserMarketDTO 的列:

<ng-template #emailCell let-userMarket>
   userMarket.email 
  <input type="text" matInput [value]="userMarket.email">
<ng-template>

以及管道发生的列定义:

<!-- Email Column -->
  <ng-container matColumnDef="email">
    <th mat-header-cell *matHeaderCellDef> Email </th>
    <td mat-cell *matCellDef="let element">
      <ng-container *ngTemplateOutlet="emailCell; context:  $implicit: element | formatEmailTo: defaultEmailValue "></ng-container>
    </td>
  </ng-container>

但这也需要更新管道以返回UserMarketDTO

public transform(userMarket: UserMarketDTO, defaultEmail: string): UserMarketDTO 
    if (!userMarket.email) 
      userMarket.email = defaultEmail;
    
    return userMarket;
  

【讨论】:

以上是关于ExpressionChangedAfterItHasBeenCheckedError:表达式在检查后已更改。以前的值:“未定义”异常的主要内容,如果未能解决你的问题,请参考以下文章