Mat-таблица с paginator, ошибка ExpressionChangedAfterItHasBeenChecked после восстановления индекса страницы - PullRequest
1 голос
/ 20 января 2020

Я был бы рад получить помощь по моей текущей ошибке, поскольку я пытаюсь найти решение в течение нескольких дней. Я хочу отобразить результат поиска, который может содержать несколько сотен элементов. Я использую mat-table с mat-paginator, чтобы избежать слишком большого количества элементов на одной странице. Код выглядит следующим образом:

<mat-paginator #paginator [pageSize]="pageSize" [length]="resultsCount">
</mat-paginator>
<table [dataSource]="itemsDS" mat-table matSort matSortDisableClear>
  <!-- rows / columns defs, nothing too fancy -->
</table>

И TS:

export class TableComponent implements OnInit {
  public itemsColumns: Array<string> = ["id", "name"];
  public itemsDS: MatTableDataSource<{
    id: number;
    name: string;
  }> = new MatTableDataSource<{ id: number; name: string }>();

  @ViewChild(MatPaginator, { static: false }) set paginator(
    paginator: MatPaginator
  ) {
    this.itemsDS.paginator = paginator;
  }

  @ViewChild(MatSort, { static: false }) set sort(sort: MatSort) {
    this.itemsDS.sort = sort;
  }

  constructor(private router: Router, private itemsService: ItemsService) {}

  ngOnInit() {
    console.log("Initializing items data");
    this.itemsDS.data = this.itemsService.items;
  }

  ngAfterViewInit() {
    if (this.itemsDS.paginator && this.itemsService.currentIndex > -1) {
      console.log("Restoring page index " + this.itemsService.currentIndex);
      this.itemsDS.paginator.pageIndex = this.itemsService.currentIndex;
    }
  }

  ngOnDestroy() {
    const currentPage = this.itemsDS.paginator.pageIndex;
    console.log("Saving page index on destroy " + currentPage);
    this.itemsService.currentIndex = currentPage;
  }

  // a few other functions like getters
}

Это сохраняет onDestroy текущую страницу, когда пользователь переходит к одному из элементов и восстанавливает этот последний просмотренный страницу, когда пользователь возвращается к результатам поиска.

Это работает нормально, но только когда сохраненный индекс страницы имеет значение 0. Всякий раз, когда пользователь переходит к элементу из индекса страницы> 1, Angular вызывает ошибку ExpressionChangedAfterItHasBeenChecked. Мой код не содержит никаких изменений в значении, которое может быть использовано где-либо выше в дереве компонентов. Так что я думаю, что это вопрос взаимодействия между mat-table и mat-paginator.

Я создал очень простой проект stackblitz , воспроизводящий это поведение, надеюсь, кто-то найдет, как обойти эта ошибка. Обратите внимание, что когда вы нажимаете item11 или item22 (первая страница), вы можете вернуться к списку без появления ошибки. Всякий раз, когда вы нажимаете item33 (вторая страница), item55 или item66 (третья страница), консоль выдает ошибку при переходе к списку.

Скомпилировано с последней angular 8 библиотеки (ядро 8.2.14 и материал 8.2.3).

Любая помощь приветствуется.

1 Ответ

1 голос
/ 10 февраля 2020

Для полноты, я добавляю сюда ответ, который получил на этот вопрос репозитория материалов :

Хитрость заключается в том, чтобы восстановить индекс страницы при вызове setTimeout:

  ngAfterViewInit() {
    if (this.itemsDS.paginator && this.itemsService.currentIndex > -1) {
      setTimeout(() => {
        this.itemsDS.paginator.pageIndex = this.itemsService.currentIndex;
        this.itemsDS.paginator.page.emit({
          length: this.itemsDS.paginator.getNumberOfPages(),
          pageIndex: this.itemsService.currentIndex,
          pageSize: this.itemsDS.paginator.pageSize
        });
      });
    }
  }

Надеюсь, это будет исправлено в течение Angular Материал за один день. Посмотрите на эту проблему (которой уже несколько лет).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...