'Extend angular-material buttons with loading animations

I'm trying to create a generic solution in Angular 12 for disabling (and displaying a spinner) when a button is clicked, until the API responses.

In order to achieve this, I intend to use a similiar approach to angular-material button. Basically, I would like to use an attribute selector for a custom button-component and apply it to the button element.

The simplified code below works as expected, but when adding the 'app-button-loading' alongside the mat-raised-button the application fails, throwing an NG0300 error: Error: NG0300: Multiple components match node with tagname button.

  <button app-button-loading color="primary"> Click me! </button>

Please note that if app-button-loading would be a Directive it would work just fine.

I tried to also specify the material selectors, but this doesn't seems to help:

selector: "button[mat-button][app-button-loading], button[mat-raised-button][app-button-loading]"

I managed to achieve a satisfying enough solution using a Directive instead of a Component with an attribute selector (programmatically creating a mat-spinner component) and it works just fine, but i would like to add some stylings and I prefer to not have them in the global styles.scss.

TL;DR; Is it possible to add a Component with an attribute selector to a button alongside with the material selector mat-raised-button (or any other)? Or Angular simply does not allow the usage of Components in this way?

<button mat-raised-button app-button-loading color="primary"> Click me! </button>

Also, I have created a simplified demo stackblitz if that helps.



Solution 1:[1]

I'm trying to create a solution in Angular 12 for disabling (and displaying a spinner) when a button is clicked, until the API responses.

If this is what you're trying to do, just use the mat-spinner component (google Mat Spinner). Your button will look like this.

<button mat-button [disabled]="apiLoading">
 <mat-spinner *ngIf="apiLoading"></mat-spinner>
 <span *ngIf="!apiLoading">Click Me</span>
</button>

Where apiLoading is a boolean in your TS file, to be toggled when your API begins.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Tu Nguyen