Programmatic Submit for Angular HostListener

February 15th 2019 Angular

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 no submit event is raised. In particular, the form's onsubmit 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.

Copyright
Creative Commons License