Я пытаюсь синхронизировать размеры страниц нескольких мат-пагинаторов, вложенных в несколько дочерних компонентов.
Я использую общий сервис для хранения «глобального» размера страницы.
Однако размер страницы обновляется во всех мат-пагинаторах, но фактический размер страницы пагинаторов не меняется.
Общий сервис:
import { EventEmitter, Injectable } from "@angular/core";
import { BehaviorSubject } from "rxjs";
@Injectable({
providedIn: 'root'
})
export class PaginatorService {
private pageSizeSubject = new BehaviorSubject<number>(10); // Default page size
pageSize$ = this.pageSizeSubject.asObservable();
setPageSize(pageSize: number) {
this.pageSizeSubject.next(pageSize);
}
}
Компонент дочерней таблицы
<table mat-table [dataSource] = "propertiesDataSource" multiTemplateDataRows class = "mat-elevation-z0" id = "properties-table" matSort>
<ng-container *ngFor = "let column of propertiesTableColumns" [matColumnDef] = "column">
<th mat-header-cell *matHeaderCellDef mat-sort-header>{{ tableHeader[column] }}</th>
<td mat-cell *matCellDef = "let lease">
<ng-container [ngSwitch] = "column">
<span *ngSwitchDefault>{{ lease[column] }}</span>
</ng-container>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef = "propertiesTableColumns; sticky:true"></tr>
<tr mat-row *matRowDef = "let property; columns: propertiesTableColumns" (click) = "openProperty(property)" class = "item-row"></tr>
</table>
<mat-paginator [pageSizeOptions] = "[10,25,50,100]" [pageSize] = "pageSize" (page) = "onPageSizeChange($event)" showFirstLastButtons>
</mat-paginator>
export class LocationDetailPropertyTableComponent implements OnInit, AfterViewInit {
@Input() properties: PropertyDtoModel[] = [];
@Input() locationCustomerID: number;
@Input() dateFilter: Date = new Date();
@ViewChild(MatPaginator) paginator: MatPaginator;
public propertiesDataSource: MatTableDataSource<PropertyDtoModel> = new MatTableDataSource();
public propertiesTableColumns = Object.keys(eTableHeader) as Array<keyof typeof eTableHeader>;
public tableHeader = eTableHeader;
public pageSize: number;
constructor(
private router: Router,
private rentersLegalLiabilityService: RentersLegalLiabilityService,
private paginatorService: PaginatorService,
private chageDetectorRef: ChangeDetectorRef
) {}
ngAfterViewInit(): void {
this.propertiesDataSource.paginator = this.paginator;
}
ngOnInit() {
this.propertiesDataSource = new MatTableDataSource(this.properties);
this.paginatorService.pageSize$.subscribe(size => {
this.pageSize = size;
this.chageDetectorRef.detectChanges(); // Manually trigger a change detection
});
}
onPageSizeChange(event: any) {
this.paginatorService.setPageSize(event.pageSize);
}
Компонент родительской страницы
<table mat-table [dataSource] = "locationDataSource" multiTemplateDataRows class = "mat-elevation-z0" id = "locations-table" matSort>
<!-- column for Expand button -->
<ng-container matColumnDef = "ExpandButton">
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef = "let location" (click) = "$event.stopPropagation()">
<button mat-icon-button (click) = "expandedLocation=expandedLocation===location ? null : location"
matTooltip = "Expand">
<span class = "mat-button-wrapper">
<mat-icon>
{{expandedLocation === location ? "expand_more": "chevron_right"}}
</mat-icon>
</span>
</button>
</td>
<td mat-foter-cell *matFooterCellDef></td>
</ng-container>
<ng-container *ngFor = "let header of tableHeaders" [matColumnDef] = "header.key">
<th mat-header-cell *matHeaderCellDef mat-sort-header>{{ header.label }}</th>
<td mat-cell *matCellDef = "let location">{{ location[header.key] }}</td>
<td mat-footer-cell *matFooterCellDef>{{ getFooterContent(header) }}</td>
</ng-container>
<!-- Expanded content column -->
<ng-container matColumnDef = "expandedDetail">
<td mat-cell *matCellDef = "let location" [attr.colspan] = "locationsTableColumns.length">
<div [@detailExpand] = "location == expandedLocation ? 'expanded' : 'collapsed'">
<location-detail-property-table [properties] = "location.LocationProperties" [locationCustomerID] = "location.LocationCustomerID" [dateFilter] = "dateFilter"></location-detail-property-table>
</div>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef = "locationsTableColumns; sticky:true"></tr>
<tr mat-row *matRowDef = "let location; columns: locationsTableColumns" class = "item-row"></tr>
<tr mat-row *matRowDef = "let row; columns: ['expandedDetail']" class = "detail-row"></tr>
<tr mat-footer-row *matFooterRowDef = "locationsTableColumns"></tr>
</table>
Я пытался принудительно обнаружить изменения, но безуспешно. После изменения нумерации страниц с 10 до 25 в другой расширенной таблице все остальные пагинаторы также должны быть обновлены до размера страницы 25.
IIRC MatTableDataSource
реагирует только на излучаемые PageEvents
, и простое изменение свойства pageSize
не генерирует эти события.
Таким образом, вам придется либо вручную вычислить правильную новую страницу и обновить page
или pageIndex
на пагинаторе, чтобы она генерировала событие, либо вы можете использовать встроенный метод _changePageSize(pageSize)
, который вычислит новый индекс страницы таким образом, чтобы гарантировать первый элемент. на странице будет по-прежнему отображаться при применении pageSize, а затем генерировать событие новой страницы. Я думаю, что _changePageSize(pageSize)
уже запускает обнаружение изменений, поэтому вы также сможете удалить его:
this.paginatorService.pageSize$.subscribe(size => {
this._changePageSize(size);
});
Вот работающий упрощенный образец на stackblitz
Я смог выполнить эту работу. Спасибо за вашу помощь. Единственное, над чем мне пришлось поработать, — это предотвратить бесконечный цикл событий, поскольку я обнаруживал изменения в pageSize с помощью события (page) в mat-paginator.