web-dev-qa-db-ja.com

angular materialでmat-paginatorをカスタマイズする方法

Mat-paginatorをカスタマイズしたいと思います。デフォルトでは、以下のリンク https://material.angular.io/components/paginator/overview で指定されているこのようなページネーターを取得しています。しかし、私は下の画像のようなページネーションが欲しいです。 mat-paginatorを使用してこれを行う方法

enter image description here

誰かがこれを手伝ってくれませんか?.

9
ananya

@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

2
Umair Hamid

[〜#〜]更新[〜#〜]2020年2月27日


@uhamidの回答をインスピレーションとして使用し、これが実際に可能であることを示す以下のいくつかのコメントとともに、私は完全なソリューションを提供するための最初の試みを修正しました。

Umair Hamid以下の例は機能的で、必要なスタイリングは含まれていません。また、ngDoCheckを利用して、再帰的な型の動作を導入し、パフォーマンスの問題を引き起こす可能性があります。

また、より完全なソリューションを作成するために、ほとんどのロジックをリファクタリングしました。

次のように使用します。

<mat-paginator style-paginator showFirstLastButtons [showTotalPages]="3" [length]="7130" [pageSize]="10" [pageSizeOptions]="[5, 10, 25, 100]"> </mat-paginator>

入力として表示するページボタンを提供する[showTotalPages]、提供されない場合、デフォルトで2


enter image description here


[〜#〜] stackblitz [〜#〜]

https://stackblitz.com/edit/angular-wyx2ue-bw95ug?embed=1&file=app/style-paginator.directive.ts

2
Marshal

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

1
borchvm

元帥は正しくない。マテリアルパジネーターの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>
0
TotenKopf

@Marshalによって提供された回答に触発された私のカスタムディレクティブ(StylePaginatorDirective)をここに見つけることができますが、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

0
pegaltier