Хороший пост! Но у меня все еще проблема с ContentChildren.
Допустим, у меня есть вкладки и компоненты вкладок:

@Component({
    selector: 'tabs',
    template: `<ng-content></ng-content>`,
    changeDetection: ChangeDetectionStrategy.OnPush,
})
export class TabsComponent implements AfterContentInit {
    @ContentChildren(TabComponent) tabs: QueryList<TabComponent>;

    ngAfterContentInit(): void {
        if (0 < this.tabs.length) {
            this.activate(this.tabs.first);
        }
    }

    activate(activatedTab: TabComponent) {
        this.tabs.forEach(tab => tab.active = false);
        activatedTab.active = true;
    }
}
@Component({
    selector: 'tab',
    template: `<ng-content></ng-content>`,
    changeDetection: ChangeDetectionStrategy.OnPush,
})
export class TabComponent {
    @Input() title: string;
    @Input() @HostBinding('class.is-active') active: boolean = false;
}

Таким образом, ContentChildren доступны только в ngAfterContentInit, и именно там я активизирую первую вкладку.

Проблема в том, что я получаю ExpressionChangedAfterItHasBeenCheckedError только из-за *ngFor:

<tabs>
    <tab *ngFor="let item of items" [title]="item.name">
        <another-component [item]="item"></another-component>
    </tab>
</tabs>

Если я сделаю активацию() тайм-аутом, ошибка исчезнет.

Не могли бы вы посоветовать какое-то решение для этого?