0

I want to change the texts by icons, what do I have to do to change the texts by icons ?

I have to find the result like this :

enter image description here

file.ts:

  ngAfterViewInit() {
    this.current.paginator = this.paginator;
    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';
    }
  }
adem
  • 31
  • 1
  • 1
  • 8
  • Text of what? Show the html that you are working on... – lingar Dec 28 '22 at 00:35
  • You can find the answer in this thread: https://stackoverflow.com/questions/47593692/how-to-translate-mat-paginator-in-angular-4 – Jimmy Dec 28 '22 at 11:31

2 Answers2

0

If you want to change the button icons, it is possible to do so.\

In order to do so, we need to alter the html that is being generated by the mat-paginator.

The following directive does it:

@Directive({
  selector: '[customPaginatorIcons]'
})
export class CustomPaginatorIcons implements AfterViewInit {

  constructor(
    private el: ElementRef,
    private renderer2: Renderer2
  ) {}

  ngAfterViewInit(): void {
    this.setFirstIcon();
    this.setPreviousIcon();
    this.setNextIcon();
    this.setLastIcon();
  }

  private replaceSvgWithIcon(
    btn: HTMLButtonElement,
    iconName: string
  ): HTMLSpanElement {
    this.renderer2.removeChild(btn, btn.querySelector('svg'));

    const icon: HTMLSpanElement = this.renderer2.createElement('span');
    this.renderer2.addClass(icon, 'material-icons');
    icon.innerHTML = iconName;

    this.renderer2.appendChild(btn, icon);
    return icon;
  }

  private setFirstIcon(): void {
    const btn = this.el.nativeElement.querySelector(
      '.mat-mdc-paginator-navigation-first'
    );

    if (btn) {
      this.replaceSvgWithIcon(btn, 'skip_previous');
    }
  }

  private setPreviousIcon(): void {
    const btn = this.el.nativeElement.querySelector(
      '.mat-mdc-paginator-navigation-previous'
    );

    if (btn) {
      const icon = this.replaceSvgWithIcon(btn, 'play_arrow');
      this.renderer2.setStyle(icon, 'transform', 'rotate(180deg)');
    }
  }

  private setNextIcon(): void {
    const btn = this.el.nativeElement.querySelector(
      '.mat-mdc-paginator-navigation-next'
    );

    if (btn) {
      this.replaceSvgWithIcon(btn, 'play_arrow');
    }
  }

  private setLastIcon(): void {
    const btn = this.el.nativeElement.querySelector(
      '.mat-mdc-paginator-navigation-last'
    );

    if (btn) {
      this.replaceSvgWithIcon(btn, 'skip_next');
    }
  }
}

Now onto the why.

  • Directive: we create our attribute directive that will adjust the icons of the MatPaginator. Attribute Directives are recommended when we only want to edit the html of something.

  • AfterViewInit: we can only edit the contents of the MatPaginator html after it has been fully initialise. The AfterViewInit lifecycle hook is the best hook for the task.

  • ElementRef: this provides access to the HTML code that our directive is placed on.

  • Renderer2: the recommended utility to modify HTML elements safely. It is the basis that directives like ngStyle and ngClass use being the scenes. We can achieve the same goal by directly editing the DOM elements, however, this may raise errors if we edit it incorrectly.

  • setFirstIcon, setPreviousIcon, setNextIcon, setLasttIcon: these are very similar methods, they search for the button that needs to be updated and if it exists, they call the replaceSvgWithIcon method to perform the actual changes. Only exception to this is the setPreviousIcon method since there is no icon that matches what you want. To achieve the look you want, I rotate the next icon.

  • replaceSvgWithIcon: starts by removing the <svg>...</svg> tag from the button. This is the tag that contains the actual image for the icon, the remaining HTML in the button element is for other things like the ripple. Once the element has been removed, we create a new HTMLSpanElement. It is on this element that we will set the material-icons class (so that it uses the Material Icons), and the value of the icon. After this is done, we append it to the provided button and return it (we return the element in case we want to modify something else that is not generic).

To use this directive, we simply call on the html selector of the paginator:

<mat-paginator 
               ...
               customPaginatorIcons>
</mat-paginator>

The above case is meant for Angular 15. For previous versions, simple remove the '-mdc' from the selectors, like so:

  • '.mat-mdc-paginator-navigation-first' to `'.mat-paginator-navigation-first';
  • '.mat-mdc-paginator-navigation-previous' to '.mat-paginator-navigation-previous';
  • '.mat-mdc-paginator-navigation-next' to '.mat-paginator-navigation-next';
  • '.mat-mdc-paginator-navigation-last' to '.mat-paginator-navigation-last';
IDK4real
  • 757
  • 6
  • 14
  • You can also create a custom-paginator component that extends from _MatPaginatorBase like the last answer of this [SO](https://stackoverflow.com/questions/70787342/how-can-i-style-mat-paginator-angular-as-shown). the paginator.html of material are in github [here](https://github.com/angular/components/blob/main/src/material/paginator/paginator.html) just change the svgs – Eliseo Jan 11 '23 at 11:38
  • 1
    That should also work, however it seems like a poor use case. You are extending an component only to modify its HTML, which is the prime use case for attribute directives. That solution opens issues in that you need to know what you are extending from, since it is not just extending and done. Consider the amount of decorator data that must also be duplicated, again, only to make it work. It is more error prone. My approach only requires that you know the css classes, which have changed rarely and are easy to check. – IDK4real Jan 11 '23 at 11:51
  • Really you has reason, it's a bit " using sledgehammers to crack nuts". Well, You can also solve using only .css – Eliseo Jan 11 '23 at 15:27
0

You can also get it only with .css

In styles.css

.mat-mdc-paginator-navigation-first svg path{
  d:path("M6.5 18q-.425 0-.713-.288Q5.5 17.425 5.5 17V7q0-.425.287-.713Q6.075 6 6.5 6t.713.287Q7.5 6.575 7.5 7v10q0 .425-.287.712Q6.925 18 6.5 18Zm10.45-1.025l-6.2-4.15q-.45-.3-.45-.825q0-.525.45-.825l6.2-4.15q.5-.325 1.025-.038q.525.288.525.888v8.25q0 .6-.525.9q-.525.3-1.025-.05Z")
}
.mat-mdc-paginator-navigation-previous svg path{
  d:path("M7.05 16.975q-.5.35-1.025.05q-.525-.3-.525-.9v-8.25q0-.6.525-.888q.525-.287 1.025.038l6.2 4.15q.45.3.45.825q0 .525-.45.825Z")
}
.mat-mdc-paginator-navigation-next svg path{
  d:path("M7.05 16.975q-.5.35-1.025.05q-.525-.3-.525-.9v-8.25q0-.6.525-.888q.525-.287 1.025.038l6.2 4.15q.45.3.45.825q0 .525-.45.825Z")
}
.mat-mdc-paginator-navigation-last svg path{
  d:path("M17.5 18q-.425 0-.712-.288q-.288-.287-.288-.712V7q0-.425.288-.713Q17.075 6 17.5 6t.712.287q.288.288.288.713v10q0 .425-.288.712q-.287.288-.712.288ZM7.05 16.975q-.5.35-1.025.05q-.525-.3-.525-.9v-8.25q0-.6.525-.888q.525-.287 1.025.038l6.2 4.15q.45.3.45.825q0 .525-.45.825Z")
}

.mat-mdc-paginator-navigation-previous svg
{
  transform:rotate(180deg) translateX(3px)
}
.mat-mdc-paginator-navigation-next svg
{
  transform:translateX(3px)
}
Eliseo
  • 50,109
  • 4
  • 29
  • 67