【问题标题】:How to customize mat-paginator in angular material如何在角度材料中自定义 mat-paginator
【发布时间】:2021-11-17 21:42:55
【问题描述】:

我想自定义 mat-paginator 。默认情况下,我得到这样的分页器,在下面的链接中给出 https://material.angular.io/components/paginator/overview。 但我想要像下图这样的分页。 我如何使用 ma​​t-paginator

做到这一点

谁能帮帮我。

【问题讨论】:

    标签: angular-material paginator


    【解决方案1】:

    更新 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
    • 感谢您的解决方案。我试过了,但是当我点击页码时它不会改变页面。此外,如果我单击 Next & Prev 按钮,那么它工作正常。请相应地更新解决方案。谢谢
    • stackblitz 示例在单击页码时不会更改页面。请更新。
    • @MrKhan 我刚刚再次修复了数字,我在按钮渲染上破坏了它们。我需要修改计算范围的算法,按钮的渲染仍然非常有问题,明天我会发布这个。我将尝试列出更改列表,但到目前为止,这是一次重大的重写。您可以将旧的 stackblitz 与新的进行比较。
    • 嗨 @MrKhan,我相信我已经整理好所有内容,并且可以查看修改后的 stackblitz 链接。
    【解决方案2】:

    在@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>
    

    现在的输出是:

    【讨论】:

      【解决方案3】:

      从 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;
        }
      }
      

      【讨论】:

        【解决方案4】:

        我想要一个带有事件发射器的前后点的自定义分页器。因此,我改进了 @marshal's 指令,清除了许多错误并进行了修改,使其与ngx-pagination 完全相同。

        只是想分享一下,如果有人需要,代码在这里Repo link

        【讨论】:

        【解决方案5】:

        您可以在此处找到我的自定义指令 (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

        【讨论】:

          【解决方案6】:

          元帅不正确。可以设置材质分页器的 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>
          

          【讨论】:

            猜你喜欢
            • 2018-06-01
            • 2022-12-05
            • 2021-04-21
            • 2018-11-21
            • 1970-01-01
            • 1970-01-01
            • 2020-02-29
            • 2016-02-12
            • 1970-01-01
            相关资源
            最近更新 更多