假设我有一个带有@ContentChildren(Child) children
的父组件。假设每个 Child
在其组件类中都有一个 index
字段。当 parent 的 child 发生变化时,我想使这些 index
字段保持最新,如下所示:
this.children.changes.subscribe(() => {
this.children.forEach((child, index) => {
child.index = index;
})
});
但是,当我尝试执行此操作时,出现“ExpressionChangedAfter...”错误,我猜这是因为此 index
更新发生在更改周期之外。这是一个演示此错误的 stackblitz:https://stackblitz.com/edit/angular-brjjrl .
我该如何解决这个问题?一种明显的方法是在模板中简单地绑定(bind) index
。第二种明显的方法是在更新其索引时为每个子项调用 detectChanges()
。假设这两种方法我都做不到,还有其他方法吗?
最佳答案
如前所述,错误来自更改周期评估 <div>{{index}}</div>
后值的更改。 .
More specifically, the view is using your local component variable
index
to assign0
... which is then changed as a new item is pushed to the array... your subscription sets the true index for the previous item only after, it has been created and added to the DOM with an index value of0
.
setTimout
或 .pipe(delay(0))
(这些本质上是同一件事)之所以有效,是因为它使更改与 this.model.push({})
的更改周期相关联。发生在...没有它的地方,更改周期已经完成,并且单击按钮时,上一个周期中的 0 在新/下一个周期中更改。
设置持续时间 500
ms 到 setTimeout 方法,你会看到它真正在做什么。
ngAfterContentInit() {
this.foos.changes.pipe(delay(0)).subscribe(() => {
this.foos.forEach((foo, index) => {
setTimeout(() => {
foo.index = index;
}, 500)
});
});
}
- 它确实允许在元素呈现后设置值
DOM,同时避免错误但是,你不会有值(value)
在构造函数或
ngOnInit
期间在组件中可用如果 你需要它。
FooComponent
中的以下内容将始终导致 0
与 setTimeout
解决方案。
ngOnInit(){
console.log(this.index)
}
Passing the index as an input like below, will make the value available during the constructor or
ngOnInit
ofFooComponent
您提到不想绑定(bind)到模板中的索引,但不幸的是,这是在元素呈现在 DOM 上之前传递索引值的唯一方法,默认值为 0
。在你的例子中。
您可以在 FooComponent
中接受索引输入
export class FooComponent {
// index: number = 0;
@Input('index') _index:number;
然后将循环中的索引传递给输入
<foo *ngFor="let foo of model; let i = index" [index]="i"></foo>
然后在 View 中使用输入
selector: 'foo',
template: `<div>{{_index}}</div>`,
This would allow you to manage the index at the
app.component
level via the*ngFor
, and pass it into the new element on the DOM as it is rendered... essentially avoiding the need to assign the index to the component variable, and also ensuring thetrue
index is provided when the change cycle needs it, at the time of render / class initialization.
堆栈 Blitz
https://stackblitz.com/edit/angular-ozfpsr?embed=1&file=src/app/app.component.html
关于javascript - 在 QueryList.changes 上更改 ContentChildren 模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55286309/