当列中有* ngIf时,mat-table中的ExpressionChangedAfterItHasBeenCheckedError

时间:2019-05-06 12:13:11

标签: angular angular-material

使用mat-table过滤器时我得到ExpressionChangedAfterItHasBeenCheckedError,而使用

<mat-icon *ngIf="parseString(element.blacklisted)" matTooltip="{{'black_listed'|translate}}" class="warning">thumb_down</mat-icon>

我正在使用Angular 7和自定义响应样式。我发现如果删除此* ngIf代码,响应式代码仍会在此代码行中给我同样的错误

<span class="mobile-label">{{'name_label'|translate}}:</span>

错误消息是这样的:

ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'ngIf: undefined'. Current value: 'ngIf: false'. It seems like the view has been created after its parent and its children have been dirty checked. Has it been created in a change detection hook ?
    at viewDebugError (core.js:16657)
    at expressionChangedAfterItHasBeenCheckedError (core.js:16645)
    at checkBindingNoChanges (core.js:16747)
    at checkNoChangesNodeInline (core.js:19618)
    at checkNoChangesNode (core.js:19607)
    at debugCheckNoChangesNode (core.js:20211)
    at debugCheckDirectivesFn (core.js:20139)
    at Object.eval [as updateDirectives] (LoanReportComponent.html:37)
    at Object.debugUpdateDirectives [as updateDirectives] (core.js:20128)
    at checkNoChangesView (core.js:19506)

这是我的html代码

<div>
      <app-alert></app-alert>
      <br />
      <app-loader></app-loader>

      <mat-form-field class="prefix-indent">
        <mat-icon matPrefix>search</mat-icon>
        <input matInput class="form-control search-box" (keyup)="updateFilter($event.target.value)" placeholder="{{'filter_label'|translate}}">

      </mat-form-field>
      <!-- Report list -->
      <div *ngIf="transaction_list.length>0">
        <mat-table mat-table #transaction [dataSource]="ds_transaction" matSort>
          <ng-container matColumnDef="name">
            <mat-header-cell *matHeaderCellDef mat-sort-header> {{'name_label'|translate}} </mat-header-cell>
            <mat-cell *matCellDef="let element">
              <span class="mobile-label">{{'name_label'|translate}}:</span>
              {{element.customer_full_name}}<mat-icon *ngIf="parseString(element.blacklisted)" matTooltip="{{'black_listed'|translate}}" class="warning">thumb_down</mat-icon>
            </mat-cell>
          </ng-container>

          <ng-container matColumnDef="transaction_dt">
            <mat-header-cell *matHeaderCellDef> {{'transaction_date'|translate}} </mat-header-cell>
            <mat-cell *matCellDef="let element">
              <span class="mobile-label">{{'transaction_date'|translate}}:</span>
              {{element.transaction_dt}}
            </mat-cell>
          </ng-container>
          <ng-container matColumnDef="application_fee">
            <mat-header-cell *matHeaderCellDef> {{'application_fee'|translate}} </mat-header-cell>
            <mat-cell *matCellDef="let element">
              <span class="mobile-label">{{'application_fee'|translate}}:</span>
              {{element.application_fee}}
            </mat-cell>
          </ng-container>
          <ng-container matColumnDef="principal">
            <mat-header-cell *matHeaderCellDef> {{'principal_label'|translate}} </mat-header-cell>
            <mat-cell *matCellDef="let element">
              <span class="mobile-label">{{'principal_label'|translate}}:</span>
              {{element.principal}}
            </mat-cell>
          </ng-container>

          <ng-container matColumnDef="currency_code">
            <mat-header-cell *matHeaderCellDef> {{'currency_code'|translate}} </mat-header-cell>
            <mat-cell *matCellDef="let element">
              <span class="mobile-label">{{'currency_code'|translate}}:</span>
              {{element.currency_code}}
            </mat-cell>
          </ng-container>

          <ng-container matColumnDef="total_interest_paid">
            <mat-header-cell *matHeaderCellDef> {{'total_interest_paid'|translate}} </mat-header-cell>
            <mat-cell *matCellDef="let element">
              <span class="mobile-label">{{'total_interest_paid'|translate}}:</span>
              {{element.total_interest_paid}}
            </mat-cell>
          </ng-container>

          <ng-container matColumnDef="total_late_fee_paid">
            <mat-header-cell *matHeaderCellDef> {{'total_late_fee_paid'|translate}} </mat-header-cell>
            <mat-cell *matCellDef="let element">
              <span class="mobile-label">{{'total_late_fee_paid'|translate}}:</span>
              {{element.total_late_fee_paid}}
            </mat-cell>
          </ng-container>

          <ng-container matColumnDef="principal_paid">
            <mat-header-cell *matHeaderCellDef> {{'principal_paid'|translate}} </mat-header-cell>
            <mat-cell *matCellDef="let element">
              <span class="mobile-label">{{'principal_paid'|translate}}:</span>
              {{element.principal_paid}}
            </mat-cell>
          </ng-container>

          <ng-container matColumnDef="total_balance_paid">
            <mat-header-cell *matHeaderCellDef> {{'total_balance_paid'|translate}} </mat-header-cell>
            <mat-cell *matCellDef="let element">
              <span class="mobile-label">{{'total_balance_paid'|translate}}:</span>
              {{element.total_balance_paid}}
            </mat-cell>
          </ng-container>

          <ng-container matColumnDef="interest_rate">
            <mat-header-cell *matHeaderCellDef> {{'interest_rate'|translate}} </mat-header-cell>
            <mat-cell *matCellDef="let element">
              <span class="mobile-label">{{'interest_rate'|translate}}:</span>
              {{element.interest_rate}}
            </mat-cell>
          </ng-container>

          <ng-container matColumnDef="cashed_out">
            <mat-header-cell *matHeaderCellDef> {{'paid_off'|translate}} </mat-header-cell>
            <mat-cell *matCellDef="let element">
              <span class="mobile-label">{{'paid_off'|translate}}:</span>
              {{element.cashed_out}}
            </mat-cell>
          </ng-container>

          <ng-container matColumnDef="status">
            <mat-header-cell *matHeaderCellDef> {{'status_label'|translate}} </mat-header-cell>
            <mat-cell *matCellDef="let element">
              <span class="mobile-label">{{'status_label'|translate}}:</span>
              {{getStatus(element.approval_status)}}
            </mat-cell>
          </ng-container>

          <ng-container matColumnDef="action">
            <mat-header-cell *matHeaderCellDef> </mat-header-cell>
            <mat-cell *matCellDef="let element">
              <button mat-raised-button (click)="lookDetail(element)" matTooltip="{{'view_detail'|translate}}" *ngIf="isAdmin">
                <mat-icon>
                  more_horiz
                </mat-icon>
              </button>&nbsp;
              <button mat-raised-button (click)="editLoan(element)" matTooltip="{{'edit_label'|translate}}" *ngIf="isAdmin">
                <mat-icon>
                  edit
                </mat-icon>
              </button>&nbsp;
            </mat-cell>
          </ng-container>

          <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
          <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>


        </mat-table>
        <mat-paginator #paginator [length]="ds_transaction.length"
                       [pageSize]="10"
                       [pageSizeOptions]="[ 10, 20, 50, 100]"
                       [showFirstLastButtons]="true">
        </mat-paginator>
      </div>

这是我的一些ts代码

@ViewChild(MatSort) set matSort(ms: MatSort) {
  this.sort = ms;
  this.setDataSourceAttributes();
}

@ViewChild(MatPaginator) set matPaginator(mp: MatPaginator) {
  this.paginator = mp;
  this.setDataSourceAttributes();
}

setDataSourceAttributes() {
  this.ds_transaction.paginator = this.paginator;
  this.ds_transaction.sort = this.sort;

  if (this.paginator && this.sort) {
    this.updateFilter('');
  }
}

ngOnInit() {
    this._userService.currentUser.takeUntil(this.ngUnsubscribe).subscribe(user => {
      if (!user) {
        this.router.navigate(['/logout']);
      } else {
        this.isAdmin = user.isAdmin;
        this.isEmployee = user.isEmployee;
        if (this.type == 'daily') {
          this.startDate = new Date();
          this.getReport();
        }
        this.translate.get('pending_label').takeUntil(this.ngUnsubscribe).subscribe(value => {

          this.pending_label = value;
          this.approved_label = this.translate.instant('approved_label');
          this.denied_label = this.translate.instant('denied_label');
        });
      }
    });
}

updateFilter(filterValue: string) {

    this.ds_transaction.filter = filterValue.trim().toLowerCase();



  if (this.ds_transaction.paginator) {
    this.ds_transaction.paginator.firstPage();
  }
}

getReport(): void {
  let sDate: string = '';
  let eDate: string = '';
  let reportName: string = '';
  if (this.type == 'daily') {
    sDate = this.datepipe.transform(this.startDate, 'yyyy-MM-dd');
    eDate = this.datepipe.transform(this.startDate, 'yyyy-MM-dd');
    reportName = 'REPORT_DAILY_ACTIVE_LOAN_TRANSACTIONS';
  } else {
    sDate = this.datepipe.transform(this.startDate, 'yyyy-MM-dd');
    eDate = this.datepipe.transform(this.endDate, 'yyyy-MM-dd');
    reportName = 'REPORT_DATE_RANGE_ACTIVE_LOAN_TRANSACTIONS';
  }
  this._backendService.getLoanReport(this._userService.getToken(), sDate, eDate, reportName)
    .takeUntil(this.ngUnsubscribe)
    .subscribe(response => {
      this.transaction_list = response.loan_transactions;
      console.log(this.transaction_list);
      if (this.transaction_list && this.transaction_list.length > 0 && this.transaction_list[0].transaction_id > 0) {
        this.ds_transaction = new MatTableDataSource<any>(this.transaction_list);
      } else {
        this.ds_transaction = new MatTableDataSource<any>();

      }
    }, (error: any) => {
      let msg = error.message ? error.message : error;
      this.alertService.error(msg);
      this._errService.handleError(error);
      this._loader.display(false);
    }, () => {
      this._loader.display(false);
    });
}

非常感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

在您的@Component对象中添加以下行: changeDetection:ChangeDetectionStrategy.OnPush

像这样:

@Component({
  changeDetection: ChangeDetectionStrategy.OnPush,
  selector: 'app-selector',
  templateUrl: './selector.component.html',
  styleUrls: ['./selector.component.scss']
})

并从'@ angular / core'导入ChangeDetectionStrategy