【发布时间】:2021-11-17 21:42:55
【问题描述】:
我想自定义 mat-paginator 。默认情况下,我得到这样的分页器,在下面的链接中给出 https://material.angular.io/components/paginator/overview。 但我想要像下图这样的分页。 我如何使用 mat-paginator
做到这一点谁能帮帮我。
【问题讨论】:
标签: angular-material paginator
我想自定义 mat-paginator 。默认情况下,我得到这样的分页器,在下面的链接中给出 https://material.angular.io/components/paginator/overview。 但我想要像下图这样的分页。 我如何使用 mat-paginator
做到这一点谁能帮帮我。
【问题讨论】:
标签: angular-material paginator
更新 08/20/2020
以@uhamid 的回答为灵感,以及下面的几个 cmets,表明这实际上是可能的,我修改了我的第一次尝试以提供完整的解决方案。
虽然下面的Umair Hamid 示例是功能性的,但它没有包含所需的样式。它还利用了ngDoCheck,它引入了递归类型行为,并可能引入性能问题。
我还重构了大部分逻辑,以获得更完整的解决方案。
像这样使用它:
<mat-paginator style-paginator showFirstLastButtons [showTotalPages]="3" [length]="7130" [pageSize]="10" [pageSizeOptions]="[5, 10, 25, 100]"> </mat-paginator>
提供页面按钮以显示为输入[showTotalPages],如果未提供,则默认为2
堆栈闪电战
https://stackblitz.com/edit/angular-wyx2ue-bw95ug?embed=1&file=app/style-paginator.directive.ts
修订版 STACKBLITZ 8/20/2020
https://stackblitz.com/edit/angular-8holwx?file=src/app/style-paginator.directive.ts
【讨论】:
在@Marshal 的帮助下,我创建了一个带有点间距的分页指令。
将此代码复制到您的指令中
import {
AfterViewInit,
Directive,
DoCheck,
Host,
Optional,
Renderer2,
Self,
ViewContainerRef,
} from '@angular/core';
import { MatPaginator } from '@angular/material';
@Directive({
selector: '[appStylePaginator]',
})
export class StylePaginatorDirective implements AfterViewInit, DoCheck {
public currentPage = 1;
public directiveLoaded = false;
public pageGapTxt = '...';
constructor(
@Host() @Self() @Optional() private readonly matPag: MatPaginator,
private readonly vr: ViewContainerRef,
private readonly ren: Renderer2,
) {}
private buildPageNumbers(pageCount, pageRange) {
let dots = false;
const paglast = pageCount;
const pagcurrent = this.matPag.pageIndex;
const showTotalPages = 8;
for (let i = 0; i < paglast; i = i + 1) {
if (
i === pagcurrent ||
(pagcurrent < showTotalPages && i < showTotalPages) ||
(i > pagcurrent - (showTotalPages - 1) && i < pagcurrent) ||
i > paglast - 1 ||
(i > pagcurrent && i < pagcurrent + showTotalPages)
) {
this.ren.insertBefore(pageRange, this.createPage(i, this.matPag.pageIndex), null);
} else {
if (i > pagcurrent && !dots) {
this.ren.insertBefore(pageRange, this.createPage(this.pageGapTxt, this.matPag.pageIndex), null);
dots = true;
}
}
}
}
private createPage(i: any, pageIndex: number): any {
const linkBtn = this.ren.createElement('mat-button');
this.ren.addClass(linkBtn, 'mat-icon-button');
const pagingTxt = isNaN(i) ? this.pageGapTxt : +(i + 1);
const text = this.ren.createText(pagingTxt + '');
this.ren.addClass(linkBtn, 'mat-custom-page');
switch (i) {
case pageIndex:
this.ren.setAttribute(linkBtn, 'disabled', 'disabled');
break;
case this.pageGapTxt:
this.ren.setAttribute(linkBtn, 'disabled', 'disabled');
break;
default:
this.ren.listen(linkBtn, 'click', () => {
this.currentPage = i;
this.switchPage(i);
});
break;
}
this.ren.appendChild(linkBtn, text);
return linkBtn;
}
private initPageRange(): void {
const pagingContainerMain = this.vr.element.nativeElement.querySelector('.mat-paginator-range-actions');
if (
this.vr.element.nativeElement.querySelector('div.mat-paginator-range-actions div.btn_custom-paging-container')
) {
this.ren.removeChild(
pagingContainerMain,
this.vr.element.nativeElement.querySelector('div.mat-paginator-range-actions div.btn_custom-paging-container'),
);
}
const pagingContainerBtns = this.ren.createElement('div');
const refNode = this.vr.element.nativeElement.childNodes[0].childNodes[0].childNodes[2].childNodes[5];
this.ren.addClass(pagingContainerBtns, 'btn_custom-paging-container');
this.ren.insertBefore(pagingContainerMain, pagingContainerBtns, refNode);
const pageRange = this.vr.element.nativeElement.querySelector(
'div.mat-paginator-range-actions div.btn_custom-paging-container',
);
pageRange.innerHtml = '';
const pageCount = this.pageCount(this.matPag.length, this.matPag.pageSize);
this.buildPageNumbers(pageCount, pageRange);
}
private pageCount(length: number, pageSize: number): number {
return Math.floor(length / pageSize) + 1;
}
private switchPage(i: number): void {
this.matPag.pageIndex = i;
this.matPag._changePageSize(this.matPag.pageSize);
}
public ngAfterViewInit() {
setTimeout(() => {
this.directiveLoaded = true;
}, 500);
}
public ngDoCheck() {
if (this.directiveLoaded) {
this.initPageRange();
}
}
}
之后,您只需在我们模块的entryComponents 中添加此指令即可。
像这样使用它:
<mat-paginator
appStylePaginator //<<== Use of directive
(page)="pageChangeEvent($event)"
[length]="pageLength"
[pageSize]="pageSize"
showFirstLastButtons
>
</mat-paginator>
【讨论】:
从 mat-paginator 插入按钮我认为这是不可能的,但您可以创建自定义寻呼机:
分页器-configurable-example.html
<button mat-button (click)="page.previousPage()"><</button>
<button mat-button (click)="updateManualPage(1)" >1</button>
<button mat-button (click)="updateManualPage(2)">2</button>
<button mat-button (click)="updateManualPage(3)">3</button>
<button mat-button (click)="page.nextPage()">></button>
<mat-paginator style="visibility:hidden" [pageIndex]="pageIndex" #page [length]="100" [pageSize]="10" [pageSizeOptions]="[5, 10, 25, 100]" (page)="pageEvent = $event" ></mat-paginator>
<div *ngIf="pageEvent">
<h5>Page Change Event Properties</h5>
<div>List length: {{pageEvent.length}}</div>
<div>Page size: {{pageEvent.pageSize}}</div>
<div>Page index: {{pageEvent.pageIndex}}</div>
</div>
paginator-configurable-example.ts
import {Component} from '@angular/core';
import {PageEvent} from '@angular/material/paginator';
/**
* @title Configurable paginator
*/
@Component({
selector: 'paginator-configurable-example',
templateUrl: 'paginator-configurable-example.html',
styleUrls: ['paginator-configurable-example.css'],
})
export class PaginatorConfigurableExample {
// MatPaginator Inputs
length = 100;
pageSize = 10;
pageSizeOptions: number[] = [5, 10, 25, 100];
manualPage = null;
// MatPaginator Output
pageEvent: PageEvent;
setPageSizeOptions(setPageSizeOptionsInput: string) {
this.pageSizeOptions = setPageSizeOptionsInput.split(',').map(str => +str);
}
public updateManualPage(index: number): void {
this.manualPage = index;
this.pageEvent.pageIndex = index;
}
public clearManualPage(): void {
this.manualPage = 0;
}
}
【讨论】:
我想要一个带有事件发射器的前后点的自定义分页器。因此,我改进了 @marshal's 指令,清除了许多错误并进行了修改,使其与ngx-pagination 完全相同。
只是想分享一下,如果有人需要,代码在这里Repo link
【讨论】:
您可以在此处找到我的自定义指令 (StylePaginatorDirective),其灵感来自 @Marshal 提供的答案,但为了显示 mat-paginator-range-label 内的分页而完全从头开始重写
预览
堆栈闪电战
https://stackblitz.com/edit/angular-wyx2ue-ayitwa?file=app%2Fstyle-paginator.directive.ts
https://angular-wyx2ue-ayitwa.stackblitz.io
定位
随意使用自定义 css 类自定义组件的顺序:https://stackoverflow.com/a/55969038/2835268
【讨论】:
元帅不正确。可以设置材质分页器的 pageIndex 属性 https://material.angular.io/components/paginator/api#MatPaginator
我完全模仿了你想要做的事情。硬编码,所以你必须弄清楚如何根据页数添加按钮,但你去吧。
<button mat-fab (click)="page.previousPage()"><</button>
<button mat-fab (click)="page.pageIndex = 0">1</button>
<button mat-fab (click)="page.pageIndex = 1">2</button>
<button mat-fab (click)="page.pageIndex = 2">3</button>
<button mat-fab (click)="page.nextPage()">></button>
<mat-paginator style="visibility:hidden" #page [length]="100" [pageSize]="10" [pageSizeOptions]="[5, 10, 25, 100]"></mat-paginator>
【讨论】: