У меня есть простой тестовый код для добавления динамических компонентов с помощью Angular 4.
@Component({
selector: 'component',
template: `
<ul><li #item *ngFor="let number of list">{{number}}</li></ul>
<ng-template #anchor> </ng-template>
<ng-template #template>
<li><input type="text" [(ngModel)]="myInput"/></li>
</ng-template>`
})
class _Component {
@ViewChild('template')
template: TemplateRef<any>
@ViewChild('anchor', { read: ViewContainerRef })
anchor: TemplateRef<any>
@ViewChildren('item', { read: ViewContainerRef })
items: QueryList<ViewContainerRef>
myInput='';
list: number[] = [0, 1, 2, 3, 4]
ngAfterViewInit() {
this.anchor.createEmbeddedView(this.template)
}
}
Все, что делает этот код, это добавляет фиктивный шаблон в конце.
Но этот код выдает исключение:
ExpressionChangedAfterItHasBeenCheckedError: выражение изменилось после проверки. Предыдущее значение: «не определено». Текущая стоимость: ''. Похоже, что представление было создано после того, как его родитель и его дочерние элементы были проверены на наличие загрязнений. Был ли он создан в хуке обнаружения изменений?
Это хорошо описательное исключение. Представление было обновлено после того, как уже проверено на изменение.
Но есть несколько вещей, которые я не понимаю здесь:
Вопрос(ы):
1:
Если я уберу input
из шаблона - теперь шаблон будет:
<ng-template #template>
<li></li>
</ng-template>
— Тогда я не получаю исключения. Это почему ?
2:
Другое решение (среди многих) — заменить ngAfterViewInit
на ngAfterContentInit
. Я уже знаю разницу между этими двумя.
Если так - могу ли я заключить (из того, что исключение пропало), что при каждом событии Angualr - происходит обнаружение изменений? (что имеет смысл, потому что ngAfterViewInit
происходит _после_ ngAfterContentInit
), поэтому, возможно, Angular обнаружил предыдущее динамическое изменение в ngAfterViewInit
? Я прав?
<ng-template #anchor
? Вы намеревались использовать<ng-container
? - person Max Koretskyi   schedule 29.05.2017