thegreyluk
thegreyluk

Reputation: 13

Angular dynamically set Button Icon iconPositionEnd

I cannot allign the icon position in a button to the end/start dynamically e.g. with Angular MatIcon attribute iconPositionEnd.

I created a Button component with the @Input() customIconPos:boolean = false;

import { Component, Input, OnInit } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatIcon, MatIconModule } from '@angular/material/icon';
import { MatToolbarModule } from '@angular/material/toolbar';

@Component({
  selector: 'button-with-loading-icon',
  standalone: true,
  imports: [MatButtonModule, MatIconModule, MatToolbarModule, MatIcon],
  templateUrl: './button-with-loading-icon.component.html',
  styleUrl: './button-with-loading-icon.component.scss',
})
export class ButtonWithLoadingIconComponent implements OnInit {
  @Input() btnText: string = '';
  @Input() customIconPos: boolean = false;
  @Input() icon: string = '';
  @Input() type: string = '';
  @Input() uiType: string = '';

  test = true;

  public ngOnInit() {}
}

Now in html I tried to make a dynamic attribute assignment:

<button mat-button mat-stroked-button class="button button-draft">
 <mat-icon [iconPositionEnd]="customIconPos">save</mat-icon>
  Als Entwurf
</button>

But it says: Can't bind to 'iconPositionEnd' since it isn't a known property of 'mat-icon'. Even though with the undynamic, static way it works and the icon is positioned to the end.

<button mat-button mat-stroked-button class="button button-draft">
  <mat-icon iconPositionEnd>save</mat-icon>
  Als Entwurf
</button>

I also tried different approaches like

<button mat-button mat-stroked-button class="button button-draft">
  <mat-icon [attr.iconPositionEnd]="customIconPos"  >save</mat-icon>
  Als Entwurf
</button>

Or

<button mat-stroked-button class="button button-draft">
  <mat-icon [iconPositionEnd]="customIconPos ? true : false" >save</mat-icon>
  Als Entwurf speichern
</button>

But they didnt work. Couldnt find any solution here on stack or in the web about it. One solution that comes to my mind is of course that one, but I dont like this approach and want to use custom attribute binding in my projects for a modular principle.

<button mat-stroked-button class="button button-draft">
  <mat-icon *ngIf="customIconPos" mat-icon iconPositionEnd>save</mat-icon>
  <mat-icon *ngIf="!customIconPos" mat-icon>save</mat-icon>
  Als Entwurf speichern
</button>

Thanks! Regards and I wish you a good day, thegreyluk

Upvotes: 0

Views: 29

Answers (1)

Naren Murali
Naren Murali

Reputation: 57986

Looking at the source code, it seems to be content projected into the button component using this below line.

Button source code - Github

<span
    class="mat-mdc-button-persistent-ripple"
    [class.mdc-button__ripple]="!_isFab"
    [class.mdc-fab__ripple]="_isFab"></span>

<ng-content select=".material-icons:not([iconPositionEnd]), mat-icon:not([iconPositionEnd]), [matButtonIcon]:not([iconPositionEnd])">
</ng-content>

<span class="mdc-button__label"><ng-content></ng-content></span>
<!-- inserted below -->
<ng-content select=".material-icons[iconPositionEnd], mat-icon[iconPositionEnd], [matButtonIcon][iconPositionEnd]">
</ng-content>

This does not evaluate [attr.iconPositionEnd]="customIconPos" or [iconPositionEnd]="customIconPos ? true : false", I think content projection does not evaluate conditional attributes, like how directives cannot be initialized conditionally using ngClass.

So to my knowledge the best solution is to just write an if else condition that add attribute manually.

<button mat-button mat-stroked-button class="button button-draft">
  @if(customIconPos) {
  <mat-icon iconPositionEnd>save</mat-icon>
  } @else {
  <mat-icon>save</mat-icon>
  } Als Entwurf
</button>

Upvotes: 0

Related Questions