【问题标题】:Making custom angular cdk-table DataSource with async pipe?使用异步管道制作自定义角度 cdk-table 数据源?
【发布时间】:2020-04-08 08:28:29
【问题描述】:

我真的很想合并 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 调用中获取数据并使用可观察对象填充数据源并使用模板中的异步管道解开这些可观察对象。 (而不是在component.ts文件中硬编码数据或订阅componenet.ts文件中的数据来实现像上面那样的自定义滚动)?

对这个端点进行 http 调用:

https://jsonplaceholder.typicode.com/users

像这样:

[dataSource]="dataSource | async"

【问题讨论】:

    标签: angular rxjs


    【解决方案1】:

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

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

    根据您提供的 stackblitz,这可能是:

    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

    【讨论】:

    • 感谢您的帮助。但我想将它与异步管道一起使用。表数据中的每一列都有一个单独的过滤器。 & 我已经根据异步数据设置了所有过滤器。我只需要实现异步管道以及带有固定标头的 cdk-virtual-scroll 功能。如果有办法在不订阅组件的情况下做到这一点,请提出建议。
    • @SpeedCode 您不能将 AsyncPipe 与 DataSource 一起使用,您也不需要这样做。只需从dataSource.connect 返回要与 AsynPipe 一起使用的 Observable。我的解决方案没有订阅组件中的任何地方。如果您有多个过滤器,您可以将它们添加到 combineLatest Observable。如果您在集成过滤器时遇到问题,请发布带有过滤器的代码。
    • 哦。好的。我的错。非常感谢。以后有没有办法和你联系? (如果我需要帮助)
    猜你喜欢
    • 2017-08-20
    • 1970-01-01
    • 1970-01-01
    • 2020-07-23
    • 1970-01-01
    • 1970-01-01
    • 2019-02-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多