【发布时间】:2017-12-08 21:29:26
【问题描述】:
我正在尝试解决一个在 AngularJS 中不存在的问题,因为 $digest-cycle 会检查所有内容。
我正在尝试创建一个组件,它可以自行初始化(异步)并通知其周围的容器加载已完成。
我有这个伪表:
<my-table>
<ng-container *ngFor="let row in rows">
<my-table-row
[row]="row"
[isLoading]="row.isLoading"
(click)="onClickRow(row)"
></my-table-row>
<my-detail-row *ngIf="row.isExpanded">
<my-component
[data]="row"
></my-component>
></my-detail-row>
</ng-container>
</my-table>
在周围的组件(包含rows)中,我有一个函数onClickRow(row),它可以切换row.isExpanded。
在my-component 组件中,我想将row.isLoading 设置为true(通知“父”行它正在加载),然后在API 调用完成后将其设置为false。
@Input() data: any;
ngOnInit() {
this.task.isLoading = true; // PROBLEM
setTimeout(() => { // simulate API call
this.task.isLoading = false; // no problem
}, 2000);
}
现在我收到此错误:Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'undefined'. Current value: 'true'.
我猜这是因为更改从 my-component 上升到 ng-container 但没有下降到 my-table-row?
我有一个解决方法,我可以在this.task.isLoading 的第一个设置周围使用第二个setTimeout(),但这会导致一些popin 效果,如果可能的话,我想找到一个更清洁的解决方案。
有没有人有建议,这如何工作?
【问题讨论】:
-
为什么不总是用
task.isLoading=true初始化,而不是从我的组件中设置它,而是在加载组件时才更新到false,这将按照你说的异步完成,你不会有这个问题 -
@Maximus 我不能将
isLoading=true设置为默认值,它控制my-table-row的可见行为(显示加载指示器)。该链接很有帮助,但有点告诉我,除了 Promise/Timeout 之外我别无选择,因为我正在做一些我不应该做的事情。但现在我想不出任何其他方法来实现这一点,即在my-componentchild 中拥有一个包含所有逻辑的“哑”表/包装组件。
标签: angular typescript angular2-changedetection