The table gets the data as an Observable from the DataSource by calling dataSource.connect
. This function should return an Observable that emits the data to display. You don't need the AsyncPipe when using a DataSource.
Pass the initial data as an Observable to your DataSource and modify this data with RxJS operators in dataSource.connect
before returning it. Terminate the Observable in dataSource.disconnect
.
Based on the stackblitz you provided this could be:
const PAGESIZE = 20;
const ROW_HEIGHT = 48;
export class GridTableDataSource extends DataSource<any> {
private initialData$: Observable<any[]>;
private onDisconnect$ = new Subject<void>();
offset = 0;
offsetChange = new BehaviorSubject(0);
constructor(
initialData$: Observable<any[]>,
private viewport: CdkVirtualScrollViewport,
private itemSize: number
) {
super();
this.initialData$ = initialData$;
this.viewport.scrollToOffset(0);
}
connect(collectionViewer: CollectionViewer): Observable<any[] | ReadonlyArray<any>> {
return combineLatest( // combine the scroll events with your initial data
this.viewport.elementScrolled().pipe( // start with a currentTarget
startWith({ currentTarget: this.viewport.getElementRef().nativeElement })
),
this.initialData$.pipe(
tap(data => this.viewport.setTotalContentSize(this.itemSize * data.length))
)
).pipe(
map(([event, initialData]: [any, any[]]) => { // map to visible data
const start = Math.floor(event.currentTarget.scrollTop / ROW_HEIGHT);
const prevExtraData = start > 5 ? 5 : 0;
// const prevExtraData = 0;
const slicedData = initialData.slice(
start - prevExtraData,
start + (PAGESIZE - prevExtraData)
);
this.offset = ROW_HEIGHT * (start - prevExtraData);
this.viewport.setRenderedContentOffset(this.offset);
this.offsetChange.next(this.offset);
return slicedData;
}),
takeUntil(this.onDisconnect$) // unsubscribe on disconnect
);
}
disconnect(collectionViewer: CollectionViewer): void {
this.onDisconnect$.next();
}
}
Pass the http request as initial data to your custom DataSource.
this.dataSource = new GridTableDataSource(
this.http.get<any[]>("https://jsonplaceholder.typicode.com/todos"),
this.viewport,
this.itemSize
);
https://stackblitz.com/edit/cdk-virtual-table-sticky-header-26g3j5