使用异步管道制作自定义角度cdk表数据源?

时间:2020-04-08 08:28:29

标签: angular rxjs

我真的很想加入cdk-virtual-scroll。但是使用cdk-virtual-scroll时,表头将不会跟随CSS粘滞位置属性。所以我碰到了一篇描述自定义滚动策略的文章。

https://stackblitz.com/edit/cdk-virtual-table-sticky-header?file=src%2Fapp%2Fapp.component.ts

在此示例中,它们扩展了数据源。

这里有硬编码的数据。

  rows = Array(200).fill(0).map((x, i) => {
    return {name: 'name' + i, id: i, age: 27};
  });

有没有一种方法可以从http调用中获取数据,并使用可观察的对象填充dataSource并使用模板中的异步管道将这些可观察的对象拆开。 (而不是对component.ts文件中的数据进行硬编码或订阅componenet.ts文件中的数据来实现上述自定义滚动)?

拨打http到此终点:

https://jsonplaceholder.typicode.com/users

赞:

[dataSource]="dataSource | async"

1 个答案:

答案 0 :(得分:0)

该表通过调用dataSource.connect从数据源中以Observable形式获取数据。此函数应返回一个Observable,该数据发出要显示的数据。使用数据源时,您不需要AsyncPipe。

将初始数据作为Observable传递到您的数据源,并在返回数据之前使用dataSource.connect中的RxJS运算符修改此数据。在dataSource.disconnect中终止Observable。

根据您提供的堆栈闪电,可能是:

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();
  }
}

将http请求作为初始数据传递到您的自定义数据源。

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