Angular Material VirtualScrollViewPort-异步加载数据

时间:2019-01-02 16:28:07

标签: angular angular-material angular7

我为VirtualScrollViewPort找到了不同的样本,但是所有这些都困扰着我如何在现实生活中使用它们。这些样本可一次从服务器加载整个数据-但由于它们太大,我想分别加载它们。我的主要要求是:

  1. 搜索掩码-用户输入一些数据
  2. 显示进度条...
  3. 在服务器上查询搜索
  4. 如果未找到结果==>显示一条消息
  5. 如果找到了东西==>显示前n(= 10)个项目
  6. 用户向下滚动后,仅剩余5件==>额外装载10件
    • 继续5。
    • 如果仅剩下3个==>结束滚动

我已经尝试过Specifying data部分中的方法-但是我无法识别没有数据加载并且无法启动视图-特别是当用户重置内容时。

我也尝试过

<cdk-virtual-scroll-viewport itemSize="itemHeight" (scrolledIndexChange)="nextBatch($event,(resultList[resultList.length-1].total) )"
class="scroll-container">
  <div *cdkVirtualFor="let search of resultList"  class="card-item" >

它可以满足第一个要求,但最后我失败了,scrolledIndexChange仅在列表中的第一项上被触发。我不知道如何跟踪用户是否已经在显示项目6(这将加载其他数据)。在API page上,@Output()旁边没有任何scrolledIndexChange

任何提示如何正确跟踪事件?

更新 我发现的第一个问题是设置高度的语法不正确,即[itemSize]="itemHeight"是适当的语法,否则它始终保持为零==>呈现所有元素!

1 个答案:

答案 0 :(得分:0)

完成一些工作后,我的最终解决方案如下:

<ng-container *ngIf="lstSearchResults|async as resultList; else searching">
  <cdk-virtual-scroll-viewport [itemSize]="itemHeight" (scrolledIndexChange)="nextBatch()"
       class="scroll-container">
     <div *cdkVirtualFor="let search of resultList"  class="card-item" >

值得注意的是,我的列表是一个异步列表,名为lstSearchResults,在ts代码中,我有:

  // for proper height and caching... (in pixels)
  itemHeight = 174;

  search(searchConfig:SearchOptions):void {
   ....
      this.lstSearchResults = new BehaviorSubject<SearchResult[]>(null);
      // call the REST service
      this.searchService.doSearch(searchConfig).subscribe(foundEntry => {
        if (!this.resultList) {
          // first list - nothing found up till now
          this.resultList = foundEntry;
        } else {
          if (!this.resultList[this.resultList.length - 1]) {
            //remove the marker (which was added below/previously)
            this.resultList.pop();
          }
          foundEntry.map(item => this.resultList.push(item));
        }
        if (this.resultList[0] && this.resultList[0].total > this.resultList.length + 1) {
          //some more elements could be fetched from the server ==> add a dummy entry for rendering
          this.resultList.push(undefined);
        }
        // notify the search list to be updated
        this.lstSearchResults.next(this.resultList);

对于滚动,我有以下代码:

  nextBatch(): void {
    if (this.theEnd) {
      return;
    }

    if (this.resultList[0]) {
      // something was found
      if (this.viewport.getRenderedRange().end === this.viewport.getDataLength()) {
        // since we scrolled to the very end of the rendered display
        // ==> check if further search is required (and do so...)
        const searchTotal = this.resultList[0].total;
        this.mySearchConfig.posOffset += this.mySearchConfig.noOfElements;
        // some basic check if the total counter exceeds the current offset 
        // i.e. no further search required
        if (this.mySearchConfig.posOffset <= searchTotal) {
          this.search(this.mySearchConfig, true);
        } else {
          this.theEnd = true;
        }
      }
    } else {
      // nothing found ==> mark the end
      this.theEnd = true;
    }
  }