5

Is there a way to get notified when a form is reset via the formReset method?

I have a directive that injects the form and I can get notified when the form is submitted or reset via a reset button but I cannot figure out a way to get notified when formRest is called on ngForm.

@Directive({
  selector: '[appForm]'
})
export class FormDirective implements OnDestroy {
  private subscription: Subscription;

  constructor(form: NgForm) {
    this.subscription = form.ngSubmit.subscribe(() => {
      console.log('submitted');
    });
    form.onReset = () => {
      console.log('reset');
    };
  }

  ngOnDestroy() {
    if (this.subscription) {
      this.subscription.unsubscribe();
    }
  }
}

Using the directive like

<form appForm #form="ngForm">
  <button type="submit">Submit</button>
  <button type="reset">Reset</button>
  <button type="button" (click)="form.resetForm()">Angular reset</button>
</form>

Is there a way to notify my directive that the resetForm method has been called?

Demo at StackBlitz https://stackblitz.com/edit/angular-adymlf?file=src/app/form.directive.ts

J. Murray
  • 1,460
  • 11
  • 19
Adrian Brand
  • 20,384
  • 4
  • 39
  • 60

1 Answers1

4

Based on w3schools onReset event, "reset" event is only triggered when the <input type="reset">. This is probably a default behaviour in browsers.

Angular's resetForm() and reset() doesn't actually trigger the reset event. It simply programatically revert the values of the form. resetForm() allows you to reset the submitted status of the angular form and also define intial values for the form to be reset to by passing in an object like this: resetForm({}).

This can be proven by adding a @HostListener('reset') in your attribute directive to listen for reset events. When form.resetForm() and form.reset() is called (or rather, clicked), reset event is not triggered at all.


Listening for clicks in Attribute Directives for buttons

To work around this, you can simply use <button type="reset">? But if it doesn't suit your use case, and you need to use <button type="button"> and still detect a reset event then you can probably add another @HostListener to listen for click events for input type of buttons:

@HostListener('click', ['$event.target']) onFormClick(btn: HTMLButtonElement){
  // console.log(btn)
  if(btn.type == "button"){
    console.log("detected click event on 'Angular reset' button, triggering reset event!");
    this.form.onReset();
  }
}

Detecting when NgForm's resetForm() is called (EDIT)


//to store original resetForm()
resetFormFunc;

constructor(private form: NgForm, private elRef: ElementRef) {

   ...

   this.resetFormFunc = form.resetForm; //assigning resetForm function to "store" it.

   //"Override" resetForm(), and call original resetForm() in the middle
   form.resetForm = () => {
     console.log("detected calling of resetForm()!");
     this.resetFormFunc.apply(form, arguments); //actually call form.resetForm()
     console.log("my additional code");
   }
}

When "Angular Reset" is clicked: enter image description here

#2 Forked Stackblitz ⚡

Hope this helps!

terahertz
  • 2,915
  • 1
  • 21
  • 33
  • The problem I am having is that the consumers of my library create the buttons, my directive is what needs to be notified of the reset happening. It is all good when a reset button can be used but that resets all the bindings to null, sometimes you need to use resetForm to pass in a model but I cannot find a way of letting my directive be notified of this happening. There is now way I am going to ask my consumers to start doing this kind of thing. – Adrian Brand Oct 02 '19 at 21:57
  • ahh my bad, I misunderstood your question. What if you tried to save the original `form.resetForm()` in a variable, and then override `resetForm()` before calling back the original resetForm(), would that work? Something like in the 2nd stackblitz I have edited in ... – terahertz Oct 03 '19 at 04:10
  • Overriding the resetForm method lets me do exactly what I need – Adrian Brand Oct 03 '19 at 06:36