Your problem is that ViewChild wont go into deeper levels when querying, so you cant query for a CdkVirtualScrollViewport in a child elements template. I could solve this with a custom change detection function in your list component.
You should remove this from your your app.ts -> addItem() function:
// want to move scroll to the top of the list
this.viewPort.scrollToIndex(0, 'smooth');
and instead create a custom change detection function in your list component, but first move the viewChild of the CdkVirtualScrollViewport to the list component:
export class ListComponent {
@ViewChild(CdkVirtualScrollViewport) viewPort: CdkVirtualScrollViewport;
@Input()
data: Favorite[];
@Output()
removeData = new EventEmitter<Favorite>();
remove($event) {
this.removeData.emit($event);
}
ngOnChanges(changes: SimpleChanges) {
if (
changes.data &&
changes.data.currentValue &&
changes.data.previousValue &&
changes.data.currentValue.length >changes.data.previousValue.length
) {
this.viewPort.scrollToIndex(0, 'smooth');
}
}
}
this works perfectly for me. Every time an item is added, it scrolls to the top.
Modified stackblitz link:
https://stackblitz.com/edit/angular-ivy-k5pve6?file=src/app/list/list.component.ts
Another solution(and maybe better) could be passing the ListComponent as a template reference to the addItem() function, then use the compononents viewPort property's scroll function.
List Component
...
export class ListComponent {
@ViewChild(CdkVirtualScrollViewport)
public viewPort: CdkVirtualScrollViewport;
...
}
AppComponentTemplate with template reference passing of the ListComponent:
<p>Start editing to see some magic happen :)</p>
<input #inputText />
<button #addButton (click)="addItem(list)">Add New</button>
<list-container #list [data]="favoriteList" (removeData)="remove($event)">
</list-container>
AppComponent-> addItem():
addItem(listComp: ListComponent) {
const newItem = {
id: Number(this.input.nativeElement.value) + 1,
title: `item ${Number(this.input.nativeElement.value) + 1}`,
};
this.favoriteList = [newItem, ...this.favoriteList];
listComp.viewPort.scrollToIndex(0, 'smooth');
}
StackBlitz for the second solution:
https://stackblitz.com/edit/angular-ivy-ofhubv?file=src/app/app.component.html