我有一个Angular Material Expansion Panel查询列表:
@ViewChildren(MatExpansionPanel)
matExpansionPanelQueryList: QueryList<MatExpansionPanel>;
和一个简单的数组:
questions: [];
扩展面板是用*ngFor
生成的:例如,简化:
<ng-container *ngFor="let question of questions>
<mat-expansion-panel
...
扩展问题数组时,我要打开最后一个扩展面板。
extendQuestion() {
this.matExpansionPanelQueryList.changes.subscribe(
change => {
change.last.open();
}
);
this.questions.push('some-new-item');
}
这很好用-我在数组中插入了一个项目,
重新渲染了ExpansionPanels,创建了一个新面板,它实际上打开了-我的问题是它在控制台中生成了以下错误:
ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has
changed after it was checked. Previous value: 'mat-expanded: false'. Current
value: 'mat-expanded: true'.
有什么办法可以避免这种情况?
我尝试在订阅中使用changeDetectorRef
和markForCheck()
,但是错误消息并没有消失(老实说,我100%确信这里的确切问题是什么)。
答案 0 :(得分:3)
这是一种警告机制,旨在防止模型数据和UI之间出现不一致,以免在页面上向用户显示错误或旧数据。
正在运行的Angular应用程序是一棵组件树。在进行变更检测期间,Angular会检查每个组件,其中每个组件都包含以指定顺序执行的以下操作:
每次操作后,Angular都会记住用于执行操作的值。它们存储在组件视图的oldValues属性中。
您可能希望在DOM更新操作之前触发组件的生命周期挂钩。
那应该对您有用:
您可以添加00:00:00
进行变更检测(cd),并在constructor
之后调用它
change.last.open();
答案 1 :(得分:0)
我找到了解决问题的方法。
通过@iLuvLogix提到的链接,强制进行更改检测解决了该问题:
constructor(private cd: ChangeDetectorRef) {}
this.matExpansionPanelQueryList.changes.subscribe(
change => {
change.last.open();
this.cd.detectChanges();
}
);
答案 2 :(得分:-2)
您可以使用javascript实现解决方案
Stackblitz Demo with javascript only
更新问题数组后,您可以使用javascript
,
,而我正在使用 setTimeout(()=>{}, 0)
将此任务放在{{1 }}
,因此在完成DOM操作后,它会在angular之后执行。
event-loop