使用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>
<button mat-raised-button (click)="editLoan(element)" matTooltip="{{'edit_label'|translate}}" *ngIf="isAdmin">
<mat-icon>
edit
</mat-icon>
</button>
</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);
});
}
非常感谢您的帮助。
答案 0 :(得分:0)
在您的@Component对象中添加以下行: changeDetection:ChangeDetectionStrategy.OnPush
像这样:
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: 'app-selector',
templateUrl: './selector.component.html',
styleUrls: ['./selector.component.scss']
})
并从'@ angular / core'导入ChangeDetectionStrategy