Как указано, ошибка возникает из-за изменения значения после оценки цикла изменения <div>{{index}}</div>
.
Более конкретно, представление использует локальную переменную компонента index
для присвоения 0
... который затем изменяется при добавлении нового элемента в массив ... ваша подписка устанавливает истинный индекс для предыдущего элемента только после того, как он был создан и добавлен в DOM со значением индекса 0
.
setTimout
или .pipe(delay(0))
(это, по сути, одно и то же) работают, потому что они сохраняют изменения, связанные с циклом изменений, в котором произошло this.model.push({})
... гдебез него цикл изменения уже завершен, и 0 из предыдущего цикла изменяется при новом / следующем цикле при нажатии кнопки.
Установите длительность 500
мс для подхода setTimeout ивы увидите, что он действительно делает.
ngAfterContentInit() {
this.foos.changes.pipe(delay(0)).subscribe(() => {
this.foos.forEach((foo, index) => {
setTimeout(() => {
foo.index = index;
}, 500)
});
});
}
- Это действительно позволяет устанавливать значение после рендеринга элемента в DOM, избегая ошибки, однако у вас не будет значения, доступного в компоненте во время конструктора или
ngOnInit
если вам это нужно.
Следующее в FooComponent
всегда приведет к 0
с решением setTimeout
.
ngOnInit(){
console.log(this.index)
}
Передачаindex в качестве входных данных, как показано ниже, сделает значение доступным во время конструктора или ngOnInit
из FooComponent
Вы упоминаете, что не хотите привязываться к индексу в шаблоне, нок сожалению, это будет единственный способ передать значение индекса до отображения элемента в 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>
Затем используйте вход в представлении
selector: 'foo',
template: `<div>{{_index}}</div>`,
Этопозволит вам управлять индексом на app.component
уровень через *ngFor
и передать его в новый элемент в DOM по мере его визуализации ... по существу, избегая необходимости назначать индекс для переменной компонента, а также гарантируя, что индекс true
предоставляется, когдацикл изменения нуждается в этом во время инициализации рендера / класса.
Stackblitz
https://stackblitz.com/edit/angular-ozfpsr?embed=1&file=src/app/app.component.html