Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular how to get button element on form submit

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?

like image 859
Curtis Avatar asked Dec 22 '22 23:12

Curtis


1 Answers

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.

like image 145
adam0101 Avatar answered Dec 25 '22 23:12

adam0101