Programmatic Submit for Angular HostListener
The HostListener
decorator can be used in Angular directives to listen to events triggered by the host element to which the directive is attached. For example, one could listen to the submit
event of a form:
@Directive({
selector: '[appInterceptSubmit]'
})
export class InterceptSubmitDirective {
@HostListener('submit', ['$event'])
onSubmit(event: Event) {
console.log('Form submitted!');
event.preventDefault();
}
}
This directive will log and cancel any submit attempts of a form it is attached to:
<form #form appInterceptSubmit>
<button #submitButton type="submit">Submit</button>
</form>
However, this will not work for any programmatic attempts to submit a form:
@ViewChild('form') form: ElementRef;
this.form.nativeElement.submit();
The HostListener
method will not be invoked. According to the submit
method documentation, this is by design:
This method is similar, but not identical to, activating a form's submit
<button>
. When invoking this method directly, however nosubmit
event is raised. In particular, the form'sonsubmit
event handler is not run.
This can be worked around by programmatically clicking the submit button instead of invoking the submit
method:
@ViewChild('submitButton') submitButton: ElementRef;
this.submitButton.nativeElement.click();
If for some reason you don't have a submit button in your form, you can take a different approach. Instead of adding a hidden submit button to it, you can programmatically dispatch a submit
event to the form:
const event = new Event('submit', { bubbles: true, cancelable: true });
if (this.form.nativeElement.dispatchEvent(event)) {
this.form.nativeElement.submit();
}
Since this submit
event is untrusted and won't automatically submit the form in all browsers, the submit
method still needs to be called. For canceling to work (using the call to preventDefault
), the event must be initialized as cancelable
and the return value of the dispatchEvent
must be checked. It will be false
if the event is canceled.