Reputation: 1483
I have pagination as shown below;
How can I replace the first and last icons with actual text to get something similar to the below. I managed to reproduce and style all other items other than replacing the first and last icons.
HTML
<mat-paginator style-paginator showFirstLastButtons [showTotalPages]="3" [refreshButtons]="dataSource.data.length" [length]="dataSource.data.length" [pageSizeOptions]="[15, 30, 45, 60]">
</mat-paginator>
style-page-directive.ts (Imported in module)
import {
ElementRef,
AfterViewInit,
Directive,
Host,
Optional,
Renderer2,
Self,
ViewContainerRef,
Input,
} from '@angular/core';
import { MatPaginator } from '@angular/material/paginator';
import { MatButton } from '@angular/material/button';
interface PageObject {
length: number;
pageIndex: number;
pageSize: number;
previousPageIndex: number;
}
@Directive({
selector: '[style-paginator]',
})
export class StylePaginatorDirective {
private _pageGapTxt = '...';
private _rangeStart: number;
private _rangeEnd: number;
private _buttons = [];
private _curPageObj: PageObject = {
length: 0,
pageIndex: 0,
pageSize: 0,
previousPageIndex: 0,
};
@Input()
get showTotalPages(): number {
return this._showTotalPages;
}
set showTotalPages(value: number) {
this._showTotalPages = value % 2 == 0 ? value + 1 : value;
}
private _showTotalPages = 2;
get inc(): number {
return this._showTotalPages % 2 == 0
? this.showTotalPages / 2
: (this.showTotalPages - 1) / 2;
}
get numOfPages(): number {
return this.matPag.getNumberOfPages();
}
get lastPageIndex(): number {
return this.matPag.getNumberOfPages() - 1;
}
@Input()
set refreshButtons(numRows: number) {
if (numRows > 0) {
this.buildPageNumbers();
this.matPag.firstPage();
}
}
constructor(
@Host() @Self() @Optional() private readonly matPag: MatPaginator,
private vr: ViewContainerRef,
private ren: Renderer2
) {
//to rerender buttons on items per page change and first, last, next and prior buttons
this.matPag.page.subscribe((e: PageObject) => {
if (
this._curPageObj.pageSize != e.pageSize &&
this._curPageObj.pageIndex != 0
) {
e.pageIndex = 0;
this._rangeStart = 0;
this._rangeEnd = this._showTotalPages - 1;
}
this._curPageObj = e;
this.initPageRange();
});
}
private buildPageNumbers() {
let roleSet = localStorage.getItem('role');
const actionContainer = this.vr.element.nativeElement.querySelector(
'div.mat-paginator-range-actions'
);
const nextPageNode = this.vr.element.nativeElement.querySelector(
'button.mat-paginator-navigation-next'
);
const prevButtonCount = this._buttons.length;
// remove buttons before creating new ones
if (this._buttons.length > 0) {
this._buttons.forEach((button) => {
this.ren.removeChild(actionContainer, button);
});
//Empty state array
this._buttons.length = 0;
}
//initialize next page and last page buttons
if (this._buttons.length == 0) {
let nodeArray =
this.vr.element.nativeElement.childNodes[0].childNodes[0].childNodes[2]
.childNodes;
setTimeout(() => {
for (let i = 0; i < nodeArray.length; i++) {
if (nodeArray[i].nodeName === 'BUTTON') {
if (nodeArray[i].innerHTML.length > 100 && nodeArray[i].disabled) {
if (roleSet == 'crew') {
this.ren.setStyle(
nodeArray[i],
'background-color',
'rgba(250, 250, 250, 1)'
);
} else if (roleSet == 'shipping' || roleSet == 'isat') {
this.ren.setStyle(
nodeArray[i],
'background-color',
'rgba(255, 255, 255, 255)'
);
} else {
this.ren.setStyle(
nodeArray[i],
'background-color',
'rgba(255, 255, 255, 255)'
);
}
this.ren.setStyle(nodeArray[i], 'color', 'white');
this.ren.setStyle(nodeArray[i], 'color', 'black');
this.ren.setStyle(nodeArray[i], 'margin', '.5%');
} else if (
nodeArray[i].innerHTML.length > 100 &&
!nodeArray[i].disabled
) {
if (roleSet == 'crew') {
this.ren.setStyle(
nodeArray[i],
'background-color',
'rgba(250, 250, 250, 1)'
);
} else if (roleSet == 'shipping' || roleSet == 'isat') {
this.ren.setStyle(
nodeArray[i],
'background-color',
'rgba(255, 255, 255, 255)'
);
} else {
this.ren.setStyle(
nodeArray[i],
'background-color',
'rgba(255, 255, 255, 255)'
);
}
this.ren.setStyle(nodeArray[i], 'color', 'white');
this.ren.setStyle(nodeArray[i], 'color', 'black');
this.ren.setStyle(nodeArray[i], 'margin', '.5%');
if (roleSet == 'crew') {
this.ren.setStyle(nodeArray[i], 'background-color', '#fafafa');
} else if (roleSet == 'shipping' || roleSet == 'isat') {
this.ren.setStyle(nodeArray[i], 'background-color', '#fff');
} else {
this.ren.setStyle(nodeArray[i], 'background-color', '#fff');
}
this.ren.setStyle(nodeArray[i], 'box-shadow', 'none');
} else if (nodeArray[i].disabled) {
if (roleSet == 'crew') {
this.ren.setStyle(nodeArray[i], 'background-color', '#fafafa');
} else if (roleSet == 'shipping' || roleSet == 'isat') {
this.ren.setStyle(nodeArray[i], 'background-color', '#fafafa');
} else {
this.ren.setStyle(nodeArray[i], 'background-color', '#fff');
}
this.ren.setStyle(nodeArray[i], 'box-shadow', 'none');
}
}
}
});
}
for (let i = 0; i < this.numOfPages; i++) {
if (i >= this._rangeStart && i <= this._rangeEnd) {
this.ren.insertBefore(
actionContainer,
this.createButton(i, this.matPag.pageIndex),
nextPageNode
);
}
if (i == this._rangeEnd) {
this.ren.insertBefore(
actionContainer,
this.createButton(this._pageGapTxt, this._rangeEnd),
nextPageNode
);
}
}
}
private createButton(i: any, pageIndex: number): any {
let roleSet = localStorage.getItem('role');
const linkBtn: MatButton = this.ren.createElement('button');
this.ren.addClass(linkBtn, 'mat-mini-fab');
this.ren.setStyle(linkBtn, 'margin', '1%');
if (roleSet == 'crew') {
this.ren.setStyle(linkBtn, 'background-color', '#fafafa');
} else if (roleSet == 'shipping' || roleSet == 'isat') {
this.ren.setStyle(linkBtn, 'background-color', '#fff');
} else {
this.ren.setStyle(linkBtn, 'background-color', '#fff');
}
this.ren.setStyle(linkBtn, 'box-shadow', 'none');
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:
let newIndex = this._curPageObj.pageIndex + this._showTotalPages;
if (newIndex >= this.numOfPages) newIndex = this.lastPageIndex;
if (pageIndex != this.lastPageIndex) {
this.ren.listen(linkBtn, 'click', () => {
console.log('working: ', pageIndex);
this.switchPage(newIndex);
});
}
if (pageIndex == this.lastPageIndex) {
this.ren.setAttribute(linkBtn, 'disabled', 'disabled');
}
break;
default:
this.ren.listen(linkBtn, 'click', () => {
this.switchPage(i);
});
break;
}
this.ren.appendChild(linkBtn, text);
//Add button to private array for state
this._buttons.push(linkBtn);
return linkBtn;
}
//calculates the button range based on class input parameters and based on current page index value. Used to render new buttons after event.
private initPageRange(): void {
const middleIndex = (this._rangeStart + this._rangeEnd) / 2;
this._rangeStart = this.calcRangeStart(middleIndex);
this._rangeEnd = this.calcRangeEnd(middleIndex);
this.buildPageNumbers();
}
//Helper function To calculate start of button range
private calcRangeStart(middleIndex: number): number {
switch (true) {
case this._curPageObj.pageIndex == 0 && this._rangeStart != 0:
return 0;
case this._curPageObj.pageIndex > this._rangeEnd:
return this._curPageObj.pageIndex + this.inc > this.lastPageIndex
? this.lastPageIndex - this.inc * 2
: this._curPageObj.pageIndex - this.inc;
case this._curPageObj.pageIndex > this._curPageObj.previousPageIndex &&
this._curPageObj.pageIndex > middleIndex &&
this._rangeEnd < this.lastPageIndex:
return this._rangeStart + 1;
case this._curPageObj.pageIndex < this._curPageObj.previousPageIndex &&
this._curPageObj.pageIndex < middleIndex &&
this._rangeStart > 0:
return this._rangeStart - 1;
default:
return this._rangeStart;
}
}
//Helpter function to calculate end of button range
private calcRangeEnd(middleIndex: number): number {
switch (true) {
case this._curPageObj.pageIndex == 0 &&
this._rangeEnd != this._showTotalPages:
return this._showTotalPages - 1;
case this._curPageObj.pageIndex > this._rangeEnd:
return this._curPageObj.pageIndex + this.inc > this.lastPageIndex
? this.lastPageIndex
: this._curPageObj.pageIndex + 1;
case this._curPageObj.pageIndex > this._curPageObj.previousPageIndex &&
this._curPageObj.pageIndex > middleIndex &&
this._rangeEnd < this.lastPageIndex:
return this._rangeEnd + 1;
case this._curPageObj.pageIndex < this._curPageObj.previousPageIndex &&
this._curPageObj.pageIndex < middleIndex &&
this._rangeStart >= 0 &&
this._rangeEnd > this._showTotalPages - 1:
return this._rangeEnd - 1;
default:
return this._rangeEnd;
}
}
//Helper function to switch page on non first, last, next and previous buttons only.
private switchPage(i: number): void {
const previousPageIndex = this.matPag.pageIndex;
this.matPag.pageIndex = i;
this.matPag['_emitPageEvent'](previousPageIndex);
this.initPageRange();
}
//Initialize default state after view init
public ngAfterViewInit() {
this._rangeStart = 0;
this._rangeEnd = this._showTotalPages - 1;
this.initPageRange();
}
}
CSS
I tried something like below but to no avail.
::ng-deep .mat-paginator-navigation-first .mat-paginator-icon {
display: none;
}
::ng-deep .mat-paginator-navigation-first {
content: "TEST" !important;
}
Upvotes: 1
Views: 2557
Reputation: 1463
You can try to set the text programatically:
const lastBtn = this.el.nativeElement.querySelector(
'.mat-paginator-navigation-last'
);
if (lastBtn) {
lastBtn.innerHTML = 'Last';
}
const firstBtn = this.el.nativeElement.querySelector(
'.mat-paginator-navigation-first'
);
if (firstBtn) {
firstBtn.innerHTML = 'First';
}
I have created a stackblitz: https://stackblitz.com/edit/angular-dy9j4m?file=src/app/table-pagination-example.ts
Upvotes: 2