Угловой MatPaginator не работает

У меня есть 2 компонента. Оба имеют мат-таблицу и paginators, а разбиение на страницы работает для одного компонента и не работает для другого компонента, хотя код похож. Ниже мой html:

<div class="mat-elevation-z8">

    <mat-table [dataSource]="dataSource" matSort>

      <ng-container matColumnDef="col1">
        <mat-header-cell *matHeaderCellDef mat-sort-header> Column1 </mat-header-cell>
        <mat-cell *matCellDef="let row"> {{row.col1}} </mat-cell>
      </ng-container>

      <ng-container matColumnDef="col2">
        <mat-header-cell *matHeaderCellDef mat-sort-header> Column2 </mat-header-cell>
        <mat-cell *matCellDef="let row"> {{row.col2}} </mat-cell>
      </ng-container>

      <!-- Different columns goes here -->

      <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
      <mat-row *matRowDef="let row; columns: displayedColumns;">
      </mat-row>
    </mat-table>

    <mat-paginator #scheduledOrdersPaginator [pageSizeOptions]="[5, 10, 20]"></mat-paginator>
  </div>

И ниже мой код в component.ts:

dataSource: MatTableDataSource<any>;
displayedColumns = ['col1', 'col2', ... ];
@ViewChild('scheduledOrdersPaginator') paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
ngOnInit(): void {
    // Load data
    this.dataSource = new MatTableDataSource(somearray);
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
}

Аналогичный код работает для другого компонента, и таблица получает визуализацию с правильной разбиением на страницы, не знаю, что не так с этим кодом.

Любая помощь могла бы быть полезна

Ответ 1

Я разрешил подобную проблему, связав экземпляр с таймаутом. Попробуй это:

setTimeout(() => this.dataSource.paginator = this.paginator);

Ответ 2

В моем случае элемент <mat-paginator> находился внутри контейнера, на котором был *ngIf, который не *ngIf до асинхронной загрузки данных. Это приводит к тому, что this.paginator не undefined даже в ngAfterViewInit. Это заставляет его молча терпеть неудачу, поскольку MatTableDataSource не имеет проблем с тем, что вы устанавливаете paginator на undefined.

Решением было переместить <mat-paginator> вне контейнера *ngIf 'd.

Надеюсь, это поможет кому-то, кто находится в той же ситуации, что и я.

Ответ 3

Несмотря на то, что выбранный ответ работает и решает проблему, это все же обходной путь. Это правильный и более элегантный способ решения проблемы.

Попробуйте добавить интерфейс AfterViewInit к вашему классу, затем поместите this.dataSource.paginator = this.paginator в ngAfterViewInit()

    ngAfterViewInit() {
        this.dataSource.paginator = this.paginator
    }

тогда вам не придется вызывать обходной путь setTimeout.

Ответ 4

Сразу после установки источника данных вызовите ChangeDetectorRef.detectChanges():

// First import ChangeDetectorRef & Material related stuff
import { ..., ChangeDetectorRef } from '@angular/core';
import { MatSort, MatTableDataSource, MatPaginator } from '@angular/material';

// Set properties in your component
@ViewChild(MatSort) sort: MatSort;
@ViewChild(MatPaginator) paginator: MatPaginator;

// Inject in constructor
constructor (..., private cdr: ChangeDetectorRef, ...) { ... }

// Set data source and invoke detectChanges()
this.dataSource = new MatTableDataSource (MY_DATA);
this.cdr.detectChanges();

// after that you can set other properties like
this.dataSource.sort = this.sort;
this.dataSource.paginator = this.paginator;

Ответ 5

Чтобы это работало, я должен был установить paginator после того, как данные были получены из источника

getVariables() {
    this.activeRoute.params.subscribe(params => {
        if (params['id'] && (params['type'] === Type.CodeList)) {
            this.dataService
                .getItems(this.currentLanguage, params['id'])
                .subscribe((items: any) => {
                    this.dataSource.data = this.items;
                    this.dataSource.paginator = this.paginator;
                })
        }
    })
}

Ответ 6

Я новичок в изучении углов и машинописи, но после того, как у меня возникла та же проблема (за исключением того, что сортировка у меня тоже не сработала), мне помогло создание функции refreshDataScource() и ее вызов из ngAfterViewInit() как а также после каждого раза, когда сервер отвечает новыми данными. В этой функции я просто dataSource с помощью пагинатора и сортировки. Как это:

refreshDataSource() {
    this.dataSource = new MatTableDataSource(myDataArray);
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
  }

Это исправило paginator и сортировку. Теперь все работает отлично. Однако я не уверен, что это просто обходной путь или реальное решение.

Ответ 7

Использование setTimeOut() временно решит проблему, однако, это снова не будет работать, если вы помещаете огромную загрузку Data [скажем 1000 строк] в MatDataSource.

мы обнаружили, что MatTable загружается очень медленно, если задан большой набор данных до того, как вы установите пагинатор источника данных.

ngOninit(){
// initialize dataSource here
}
    ngAfterViewInit() {
  this.dataSource.sort = this.sort;
  this.dataSource.paginator = this.paginator;

  /* now it okay to set large data source... */
  this.dataSource.data = [GetLargeDataSet];}

Итак, сначала инициализируйте источник данных и установите свойства, такие как "Paginator" или "Sort", прежде чем помещать данные в источник в свойство "Data".

Ответ 8

Решение, которое я нахожу, состоит в том, чтобы установить paginator после успешной загрузки данных.

this._empService.GetEmpList().subscribe(
  data => {
    this.empListDataSource = new MatTableDataSource<empToShow>(Object.values(data))
    this.empListDataSource.paginator = this.paginator
  }
)

Ответ 9

Только изменить

dataSource: MatTableDataSource<any>;

за

dataSource = new MatTableDataSource();
dataSource = new MatTableDataSource();
displayedColumns = ['col1', 'col2', ... ];
@ViewChild('scheduledOrdersPaginator') paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
ngOnInit(): void {
    // Load data
    this.dataSource = new MatTableDataSource(somearray);
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
}

Ответ 10

У меня была такая же проблема (отображение данных таблицы, но MatPaginator не работает). В моем случае я забыл создать "новый MatTableDataSource"

this.dataSource = somearray;

не включать MatPaginator, в то время как this.dataSource = new MatTableDataSource(somearray); делает.

выписка из материалов документации

"Чтобы упростить вариант использования таблицы, которая может сортировать, разбивать на страницы и фильтровать массив данных, библиотека Angular Material поставляется с MatTableDataSource, в котором уже реализована логика определения того, какие строки должны отображаться в соответствии с текущим состоянием таблицы. ".

надеюсь, что этот ответ кому-то поможет.

Ответ 11

После того, как все вышеперечисленные решения были опробованы, у меня, наконец, сработало простое решение. Я отправляю для справки, если кто-то застрял.

Я использую Angular 8. Просто добавьте {static: false} в дочернюю ссылку

  @ViewChild(MatSort, { static: false }) sort: MatSort;
  @ViewChild(MatPaginator, {static: false}) paginator: MatPaginator;

Получил решение отсюда

Я использовал это:

@ViewChild (MatSort, {read: true, static: false}) sort: MatSort;

@ViewChild (MatPaginator, {read: true, static: false}) paginator: MatPaginator;

Ответ 12

  <mat-paginator
        #scheduledOrdersPaginator
          (page)="pageEvent($event)">
        </mat-paginator>
         pageEvent(event){
         //it will run everytime you change paginator
           this.dataSource.paginator = this.paginator;
          }

Ответ 13

Решение без использования setTimeout заключается в использовании set:


 @ViewChild(MatPaginator) paginator: MatPaginator;


 set matPaginator(mp: MatPaginator) {
      this.paginator = mp;
      this.dataSource.paginator = this.paginator;
  }

Ответ 14

В моем случае данные поступают из службы асинхронно, поэтому ни один из них не может использовать ngOnInit или ngAfterViewInit, я использовал ngOnChanges, что-то вроде ниже:

ngOnChanges(change: SimpleChanges) {
    if (change.properties) {
      if (this.properties.length > 0) {
        this.dataSource = new MatTableDataSource(this.properties);
        this.dataSource.paginator = this.paginator;
      }
    }
  }

Ответ 15

Мне потребовались часы, чтобы, наконец, отследить и понять, почему мой стол не работал. Размещение некоторых console.logs() помогло мне выяснить порядок событий и почему он не работал последовательно. Мой сценарий был похож на исходную проблему выше с динамическим источником данных, но немного отличался. Для меня, когда я сначала обновил свое угловое приложение, было бы установлено состояние пагинатора, а затем были бы установлены данные для моей таблицы. Когда эти события произошли бы в этом порядке, пагинатор работал так, как ожидалось.

Поскольку я использовал ReplaySubjects для получения данных для моих таблиц, мое состояние разбивки на страницы будет установлено в ngAfterViewInit, а затем данные таблицы будут поступать из моей подписки (это зависит от идентификатора пользователя, поэтому у меня нет начального значения, и это почему я не использовал BehaviorSubjects). Моя проблема заключалась в том, что, когда я переходил к другому компоненту в моем приложении и возвращался к своему источнику данных динамической таблицы, данные таблицы устанавливались бы до состояния пагинации. Это заставит paginator показывать страницу x, но отображаемые данные всегда будут первой страницей данных.

Чтобы исправить эту досадную проблему, я:

  1. Написал простую функцию для установки данных моей таблицы, как кто-то упоминал выше:
  setTableData() {
    // set table data
    this.tableData.data = this.images.filter(img => this.filterData(img));

    // some other code below
    ....
  }
  1. Добавлены два флага в мой компонент, один для того, если я загрузил данные таблицы, и один для, если мое состояние пагинации было установлено. Таким образом, я мог убедиться, что состояние пагинации установлено перед данными.
  // initialize our data source for our table and set flags for state
  tableData = new MatTableDataSource<IImage>(this.images);
  loading = true;
  setPageState = false;
  1. Добавил setTimeout в ngAfterViewInit, который установил бы мое состояние paginator и установил данные моей таблицы, только если данные таблицы были получены до вызова ngAfterViewInit. SetTimeout предотвращает надоедливую ошибку "выражение изменилось после проверки значения".
  ngAfterViewInit() {
    // add pagination state to our table
    setTimeout(() => {
      console.log('Set paginator state');
      this.setPageState = true;
      this.paginator.pageIndex = this.state.pageIndex;

      // check if we are not loading data, meaning the table came in first so
      // we need to set the data here
      if (!this.loading) {
        this.setTableData();
      }
    }, 0);
  }
  1. Наконец, в ngOnInit, где я подписываюсь на свои данные, я не устанавливаю свои данные таблицы, если сначала не было установлено состояние paginator:
  ngOnInit() {
    console.log('ngOnInit');
    this.tableData.sort = this.sort;
    this.tableData.paginator = this.paginator;

    // listen for data
    this.dbService.images.subscribe(images => {
      console.log('Data subscription');
      // save images
      this.images = images;

      // only set table data if paginator state has been set, otherwise it doesnt work
      if (this.setPageState) {
        this.setTableData();
      }

      // hide spinner and update that we have data
      this.loading = false;
    });

    // other code
    .....
  }

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

Ответ 16

У меня тоже была эта проблема. Я добавил ссылку scheduleOrdersPaginator в тег pagintaor и получил с помощью @ViewChild. Это решило мою проблему с нумерацией страниц. Ниже код может помочь другим.

dataSource = new MatTableDataSource();
displayedColumns = ['col1', 'col2', ... ];
@ViewChild('scheduledOrdersPaginator') paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
ngOnInit(): void {
    // Load data
    this.dataSource = new MatTableDataSource(somearray);
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
}

HTML:

<mat-paginator #scheduledOrdersPaginator [pageSizeOptions]="[5, 10, 20]" showFirstLastButtons> </mat-paginator> 

Ответ 17

Проверьте этот fooobar.com/questions/14769545/....

Установка paginator в машинописном тексте после загрузки компонентов HTML (* ngIf) исправила проблему для меня.

Ответ 18

введите описание ссылки здесь Чтобы разбить данные таблицы на страницы, добавьте после таблицы.

Если вы используете MatTableDataSource для своего источника данных таблицы, просто предоставьте MatPaginator своему источнику данных. Он автоматически прослушивает изменения страницы, сделанные пользователем, и отправляет правильные выгруженные данные в таблицу.

В противном случае, если вы реализуете логику для разбивки на страницы ваших данных, вы захотите прослушать вывод страницы (страницы) и передать правильный фрагмент данных в свою таблицу.

Дополнительную информацию об использовании и настройке см. в документах mat-paginator.

MatPaginator - это одно из предоставляемых решений для разбивки данных таблицы, но это не единственный вариант. Фактически таблица может работать с любым пользовательским интерфейсом или стратегией разбивки на страницы, поскольку MatTable и его интерфейс не привязаны к какой-либо конкретной реализации.

@ViewChild(MatPaginator, {static: true}) paginator: MatPaginator;
ngOnInit() {
  this.dataSource.paginator = this.paginator;
}

Ответ 19

Убедитесь, что вы импортировали MatPaginatorModule в app.module.ts

Ответ 20

Ни одно из вышеуказанных решений не помогло мне.

Я выяснил, в чем была проблема, в основном this.paginator будет неопределенным, пока таблица не будет загружена и, следовательно, в некоторых местах решение setTimeout работает.

Но в моем случае моя таблица была скрыта за некоторой логикой ngIf, поэтому таблица была загружена только после того, как ngIf станет истинным (что происходит при взаимодействии с пользователем), но я установил this.dataSource.paginator = this.paginator на ngOnInit

Таким образом, решение зависит от вашего случая, основная правда заключается в том, что таблица загружается только тогда this.dataSource.paginator = this.paginator

Я решил это, когда пользователь делает пересечение, и ngIf становится true, после чего я вызываю функцию для установки пагинатора

     initPaginator(){
        this.dataSource.paginator = this.paginator
}

Ответ 21

Использование setTimeout() является жизнеспособным решением, только если вы знаете, сколько времени потребуется для загрузки таблицы. Моя проблема заключалась в том, что я использовал * ngIf для таблицы (с! IsLoading):

this.dataSource = new MatTableDataSource(this.rawData);

this.initPaginator();

this.isLoading = false;

Исправление устанавливало для моей переменной isLoading значение false только после обнаружения изменений и инициализации страницы:

this.dataSource = new MatTableDataSource(this.rawData);

this.isLoading = false;

this.cdr.detectChanges();

this.initPaginator();

Таким образом, он загружает данные → показывает таблицу → обнаруживает изменения → inits paginator. Надеюсь, это кому-нибудь поможет!