I frequently find myself wanting to disable a button once it has been pressed on a form. So I do something like this:
<button (click)="complete($event.target)">
and then in my typescript file I turn it off until the action is completed like so:
complete(button: HTMLButtonElement): void {
button.disabled = true;
this.service.doSomething.subscribe(..., ..., () => button.disabled = false);
}
I could achieve that exact same thing by tagging the button and then using a ViewChild
instead. Other than personal preference, is there a good reason to use one vs. the other?
@ViewChild
is mainly for when you need an instance of a component and it's properties, usually as a parent component abstracting some logic away from the child. You get the whole child class as a property in the parent class and can do what you will with it. It's also used as one method to grab a DebugElement
off the DOM.
Template binding can sort of be thought of as interacting with a component via its "API". It's made Inputs
and Outputs
available to the component that's using it in situations where those interactions can provide full functionality. Angular handles those inputs and outputs in its own zone and change detection cycles.
Having said that, using @viewChild
to get a component would allow you to interact with it directly the same way you'd do with template binding, though there's often little reason to do that.
Having said that, you're talking about pulling a @ViewChild
of an HTML element. There's a lot of reasons why you shouldn't interact with the DOM directly in Angular. The framework completely abstracts the DOM from code, and there's reasons behind that.
I think best practice here would be to let the component represent the button's state and allow Angular to alter the view for you:
<button (click)="complete($event.value)" [disabled]="formDisabled">
component.ts:
public formDisabled = false;
complete(value: string): void {
this.formDisabled = true;
this.service.doSomething.subscribe(..., ..., () => this.disabled = false);
}
This lets Angular handle change detection and view rendering within the framework while the component itself represents state.
This can get even slicker with NgForms
, as you can bind the disabled property to the form's state itself. There's even some hooks for pending submission states and asynchronous validators!.