Angular Material VirtualScrollViewPort - загрузка данных асинхронна - PullRequest
0 голосов
/ 02 января 2019

Я нахожу разные образцы для 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 Я не вижу никаких @Output() рядом с scrolledIndexChange.

Нет подсказок, как правильно отслеживать события?

ОБНОВЛЕНИЕ Первой проблемой, которую я выяснил, был неправильный синтаксис установки высоты, т. Е. [itemSize]="itemHeight" - подходящий синтаксис, в противном случае он всегда остается равным нулю ==> все элементы отображаются!

1 Ответ

0 голосов
/ 08 января 2019

После некоторой работы мое окончательное решение выглядит следующим образом:

<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;
    }
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...