Ответ 1
Я разрешил подобную проблему, связав экземпляр с таймаутом. Попробуй это:
setTimeout(() => this.dataSource.paginator = this.paginator);
У меня есть 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;
}
Аналогичный код работает для другого компонента, и таблица получает визуализацию с правильной разбиением на страницы, не знаю, что не так с этим кодом.
Любая помощь могла бы быть полезна
Я разрешил подобную проблему, связав экземпляр с таймаутом. Попробуй это:
setTimeout(() => this.dataSource.paginator = this.paginator);
В моем случае элемент <mat-paginator>
находился внутри контейнера, на котором был *ngIf
, который не *ngIf
до асинхронной загрузки данных. Это приводит к тому, что this.paginator
не undefined
даже в ngAfterViewInit
. Это заставляет его молча терпеть неудачу, поскольку MatTableDataSource
не имеет проблем с тем, что вы устанавливаете paginator
на undefined
.
Решением было переместить <mat-paginator>
вне контейнера *ngIf
'd.
Надеюсь, это поможет кому-то, кто находится в той же ситуации, что и я.
Несмотря на то, что выбранный ответ работает и решает проблему, это все же обходной путь. Это правильный и более элегантный способ решения проблемы.
Попробуйте добавить интерфейс AfterViewInit
к вашему классу, затем поместите this.dataSource.paginator = this.paginator
в ngAfterViewInit()
ngAfterViewInit() {
this.dataSource.paginator = this.paginator
}
тогда вам не придется вызывать обходной путь setTimeout
.
Сразу после установки источника данных вызовите 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;
Чтобы это работало, я должен был установить 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;
})
}
})
}
Я новичок в изучении углов и машинописи, но после того, как у меня возникла та же проблема (за исключением того, что сортировка у меня тоже не сработала), мне помогло создание функции refreshDataScource()
и ее вызов из ngAfterViewInit()
как а также после каждого раза, когда сервер отвечает новыми данными. В этой функции я просто dataSource
с помощью пагинатора и сортировки. Как это:
refreshDataSource() {
this.dataSource = new MatTableDataSource(myDataArray);
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
}
Это исправило paginator и сортировку. Теперь все работает отлично. Однако я не уверен, что это просто обходной путь или реальное решение.
Использование 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".
Решение, которое я нахожу, состоит в том, чтобы установить paginator после успешной загрузки данных.
this._empService.GetEmpList().subscribe(
data => {
this.empListDataSource = new MatTableDataSource<empToShow>(Object.values(data))
this.empListDataSource.paginator = this.paginator
}
)
Только изменить
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;
}
У меня была такая же проблема (отображение данных таблицы, но MatPaginator не работает). В моем случае я забыл создать "новый MatTableDataSource"
this.dataSource = somearray;
не включать MatPaginator, в то время как this.dataSource = new MatTableDataSource(somearray);
делает.
выписка из материалов документации
"Чтобы упростить вариант использования таблицы, которая может сортировать, разбивать на страницы и фильтровать массив данных, библиотека Angular Material поставляется с MatTableDataSource, в котором уже реализована логика определения того, какие строки должны отображаться в соответствии с текущим состоянием таблицы. ".
надеюсь, что этот ответ кому-то поможет.
После того, как все вышеперечисленные решения были опробованы, у меня, наконец, сработало простое решение. Я отправляю для справки, если кто-то застрял.
Я использую 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;
<mat-paginator
#scheduledOrdersPaginator
(page)="pageEvent($event)">
</mat-paginator>
pageEvent(event){
//it will run everytime you change paginator
this.dataSource.paginator = this.paginator;
}
Решение без использования setTimeout
заключается в использовании set
:
@ViewChild(MatPaginator) paginator: MatPaginator;
set matPaginator(mp: MatPaginator) {
this.paginator = mp;
this.dataSource.paginator = this.paginator;
}
В моем случае данные поступают из службы асинхронно, поэтому ни один из них не может использовать 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;
}
}
}
Мне потребовались часы, чтобы, наконец, отследить и понять, почему мой стол не работал. Размещение некоторых console.logs() помогло мне выяснить порядок событий и почему он не работал последовательно. Мой сценарий был похож на исходную проблему выше с динамическим источником данных, но немного отличался. Для меня, когда я сначала обновил свое угловое приложение, было бы установлено состояние пагинатора, а затем были бы установлены данные для моей таблицы. Когда эти события произошли бы в этом порядке, пагинатор работал так, как ожидалось.
Поскольку я использовал ReplaySubjects для получения данных для моих таблиц, мое состояние разбивки на страницы будет установлено в ngAfterViewInit, а затем данные таблицы будут поступать из моей подписки (это зависит от идентификатора пользователя, поэтому у меня нет начального значения, и это почему я не использовал BehaviorSubjects). Моя проблема заключалась в том, что, когда я переходил к другому компоненту в моем приложении и возвращался к своему источнику данных динамической таблицы, данные таблицы устанавливались бы до состояния пагинации. Это заставит paginator показывать страницу x, но отображаемые данные всегда будут первой страницей данных.
Чтобы исправить эту досадную проблему, я:
setTableData() {
// set table data
this.tableData.data = this.images.filter(img => this.filterData(img));
// some other code below
....
}
// initialize our data source for our table and set flags for state
tableData = new MatTableDataSource<IImage>(this.images);
loading = true;
setPageState = false;
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);
}
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
.....
}
И с этим моя нумерация страниц наконец-то работала последовательно, когда я впервые захожу в приложение и когда я перехожу на другие страницы и возвращаюсь к своей динамической таблице.
У меня тоже была эта проблема. Я добавил ссылку 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>
Проверьте этот fooobar.com/questions/14769545/....
Установка paginator в машинописном тексте после загрузки компонентов HTML (* ngIf) исправила проблему для меня.
введите описание ссылки здесь Чтобы разбить данные таблицы на страницы, добавьте после таблицы.
Если вы используете MatTableDataSource для своего источника данных таблицы, просто предоставьте MatPaginator своему источнику данных. Он автоматически прослушивает изменения страницы, сделанные пользователем, и отправляет правильные выгруженные данные в таблицу.
В противном случае, если вы реализуете логику для разбивки на страницы ваших данных, вы захотите прослушать вывод страницы (страницы) и передать правильный фрагмент данных в свою таблицу.
Дополнительную информацию об использовании и настройке см. в документах mat-paginator.
MatPaginator - это одно из предоставляемых решений для разбивки данных таблицы, но это не единственный вариант. Фактически таблица может работать с любым пользовательским интерфейсом или стратегией разбивки на страницы, поскольку MatTable и его интерфейс не привязаны к какой-либо конкретной реализации.
@ViewChild(MatPaginator, {static: true}) paginator: MatPaginator;
ngOnInit() {
this.dataSource.paginator = this.paginator;
}
Убедитесь, что вы импортировали MatPaginatorModule
в app.module.ts
Ни одно из вышеуказанных решений не помогло мне.
Я выяснил, в чем была проблема, в основном this.paginator
будет неопределенным, пока таблица не будет загружена и, следовательно, в некоторых местах решение setTimeout
работает.
Но в моем случае моя таблица была скрыта за некоторой логикой ngIf
, поэтому таблица была загружена только после того, как ngIf
станет истинным (что происходит при взаимодействии с пользователем), но я установил this.dataSource.paginator = this.paginator
на ngOnInit
Таким образом, решение зависит от вашего случая, основная правда заключается в том, что таблица загружается только тогда this.dataSource.paginator = this.paginator
Я решил это, когда пользователь делает пересечение, и ngIf
становится true
, после чего я вызываю функцию для установки пагинатора
initPaginator(){
this.dataSource.paginator = this.paginator
}
Использование 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. Надеюсь, это кому-нибудь поможет!