如何在角形材料中自定义垫子分页器

时间:2018-12-06 07:11:17

标签: angular-material paginator

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

enter image description here

有人可以帮我吗?

6 个答案:

答案 0 :(得分:6)

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

现在输出为: enter image description here

答案 1 :(得分:1)

我想要一个带有事件发射器的,带有正反两个点的自定义分页器。因此,我通过清除许多错误来改进 @marshal的指令,并进行了修改,使其与ngx-pagination完全一样。

只是想分享一下,以防万一有人需要,代码在这里Repo link

Custom Pagination

答案 2 :(得分:0)

我认为这是个很好的机会,可以确切地了解我可以对材质库组件进行指令DOM操作能走多远……感觉我做得还不错,但是……我得出结论,这不会可能...这仍然是一次很好的学习经历。

  
      
  • 也许有比我更富有经验的人可以对此进行更深入的探讨,甚至可以发表更好的评论。
  •   
  • 但是对于我使用指令的经验水平,我相信这不可能通过指令/ DOM操作来实现
  •   

enter image description here


我将避免您进行所有更改以产生这种堆叠闪电,并直接了解为什么我相信这是不可能的。

以下是分页程序用于遍历数组的4种方法

  • firstPage()
  • previousPage()
  • nextPage()
  • lastPage()

https://github.com/angular/material2/blob/63be232283262615fa2130900c80dd570eff6cda/src/lib/paginator/paginator.html#L58

没有一个将接受索引或值,因此无法在屏幕快照中具有按钮1-6……因为从理论上讲,它们只能使用上述4种方法之一。

我确实设法插入了一个按钮3,以查看是否可以通过指令使用这些方法之一……因为您可以看到单击该按钮时当前会发出警报。

  • 我无法使用上述方法之一,无法完全确定如何进行连接...或者甚至可能。
  • 鉴于无法将值传递给这些方法,并且无法弄清楚如何发出点击事件,并无法通过Renderer2将其连接到组件方法,我觉得这是不可能的。

Stackblitz

https://stackblitz.com/edit/angular-wyx2ue?embed=1&file=app/paginator-overview-example.html


结论

如前所述,这对我来说是使用指令的不错的学习经历...但是我认为以一种能够满足您要求的方式对分页器进行品牌化是不可能的,您应该探索一个替代库来满足您的要求。< / p>

答案 3 :(得分:0)

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

答案 4 :(得分:0)

您可以在这里找到我的自定义指令(StylePaginatorDirective),其灵感来自@Marshal提供的答案,但已完全从头重写,以显示mat-paginator-range-label内的分页

预览

enter image description here

Stackblitz

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

随意自定义组件的顺序。

答案 5 :(得分:0)

插入mat-paginator中的按钮,我认为这是不可能的,但是您可以创建自定义传呼机:

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

example image