In my Angular 11 (Ionic 5) app, I have a scenario with two components: A ContainerComponent
and a BoxComponent
.
Both of these components are completely transparent (
template: '<ng-content></ng-content>'
).
The challenge is for the container component to keep track of the number of box components that are placed into it by a third component.
However, my solution fails when the third component uses *ngFor directive to insert the boxes into the container (Option B below).
container.component.ts
import { Component, ContentChildren, QueryList, AfterContentInit } from '@angular/core';
import { BoxComponent } from './box.component';
@Component({
selector: 'container',
template: '<ng-content></ng-content>',
styleUrls: ['container.component.scss'],
})
export class ContainerComponent implements AfterContentInit {
// keeping track of the number of boxes
private count: number = 0;
@ContentChildren(BoxComponent)
private boxes!: QueryList<BoxComponent>;
ngAfterContentInit(): void {
this.count++;
console.log(count); // See result below
}
}
The third component inserts n
BoxComponent
s into a ContainerComponent
.
Option A: n boxes hardcoded into the template of the third component
<container>
<box>Box 1</box>
<box>Box 2</box>
// ...
<box>Box n</box>
</container>
Option B: n boxes dynamically added into the template of the third component using *ngFor directive
<container *ngFor="let box of boxes">
<box>{{box.label}}</box>
</container>
Difference between option A and option B
When opting for option A, Angular triggers ngAfterContentInit
only once resulting in
count = n
However, with option B, Angular calls ngAfterContentInit
n times leading to a constant value of 1 for count
.
count = 1, 1, ..., 1 // repeated n times
I find this behavior quite peculiar as it implies that Angular generates a new instance of ContainerComponent
for each BoxComponent
.