I have a page with multiple forms on it. Each form has a number of buttons on it. I would like to implement a loading spinner on buttons after they are pressed. When I use a normal click event I can pass in the button:
HTML
<button #cancelButton class="button-with-icon" type="button" *ngIf="hasCancel" mat-raised-button color="warn" [disabled]="isLoading" (click)="clickEvent(cancelButton)">
<mat-spinner *ngIf="isLoading" style="display: inline-block;" diameter="24"></mat-spinner>
Cancel
</button>
TS
clickEvent(button: MatButton) {
console.log(button);
}
In this case the button element gets passed through and you can access it in order to add a loading class to the button.
However, if you try the same thing using a submit button it comes through as undefined
:
HTML
<form (ngSubmit)="save(saveButton)">
<button #saveButton class="button-with-icon" type="submit" *ngIf="hasSave" mat-raised-button color="primary" [disabled]="isLoading">
<mat-spinner *ngIf="isLoading" style="display: inline-block;" diameter="24"></mat-spinner>
Save
</button>
</form>
TS
save(button: MatButton) {
console.log(button);
}
In this case button is undefined
because the *ngIf
on the button blocks it from the scope of the form. I could remove the *ngIf
and just hide the button, but this leaves the button on the DOM and I do not want to do that.
Here is a stack blitz: https://stackblitz.com/edit/angular-zh7jcw-mrqaok?file=app%2Fform-field-overview-example.html
I have tried adding an additional click event to the save button to set the button to loading but the click event fires first and set the button to disabled before blocking the submit event from being called.
Ive looked through the submit event but cant see anything that links back to the button that was clicked.
Any suggestions?
Update I understand your particular issue now. The problem is the *ngIf
on the button. It's breaking the reference. Change it to [hidden]
and it should work. Here's an updated StackBlitz: https://stackblitz.com/edit/angular-zh7jcw-pcuuyv
As for why it happen, I think this describes the problem pretty well: https://stackoverflow.com/a/36651625/64279
Original answer:
I wouldn't even pass it in. Just add this in your class:
@ViewChild('saveButton') button;
Then you can reference it in your save method:
save() {
console.log(this.saveButton);
}
But I will also add that calling function from interpolation is not a good idea as it can cause performance issues. Rather, you should subscribe to an event which sets a property, then reference that property in your view. That way, the function is only called when the event fires instead of every rendering of the page.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With