I'm trying to create a behavior where all my forms that are attached to a preventFormChangesLoss
directive will behave so that if there are changes to the form (if it's not pristine
or submitted
), the page shows a warning when the user wants to leave.
For that, I am trying to get my directive to get the NgForm instance my directive is attached to. For now, I have
import { Directive, Input, ElementRef, OnInit, AfterViewInit, ViewChild } from '@angular/core';
import { NgForm } from '@angular/forms';
@Directive({
selector: '[preventFormChangesLoss]'
})
export class PreventFormChangesLoss implements OnInit, AfterViewInit {
private origin: string = '';
@ViewChild('myForm') form : NgForm;
constructor(private elRef: ElementRef) {
console.log(this.elRef);
}
ngOnInit() {
console.log(this.elRef, this.form);
}
ngAfterViewInit() {
console.log(this.elRef, this.form); // shows the native element, + 'undefined'
}
}
And I use it with
<form preventFormChangesLoss #myForm="ngForm">
...
</form>
Unfortunately, this does not work, and I also would like my directive to get the NgForm instance without having to do the #myForm="ngForm"
part, so that I can name my forms however I want and keep this behavior separate.
How can I do that, and can someone point me to the right place in the docs?
You cannot grab the form element like that because it's not part of directive's view. Instead you should directly inject it.
import { Directive, Input, ElementRef, OnInit } from '@angular/core';
import { NgForm } from '@angular/forms';
@Directive({
selector: '[preventFormChangesLoss]'
})
export class PreventFormChangesLoss implements OnInit {
private origin: string = '';
constructor(private ngForm: NgForm) {
console.log(this.ngForm);
}
ngOnInit() {
console.log(this.ngForm)
}
}
This will allow you to manipulate and subscribe to events of the specific Angular-enhanced <form>
from within the directive, so you'll only be using it like so:
<form preventFormChangesLoss>
...
</form>
Not as per your design, but a tip: Since you said that you want to do this for all your forms, it might be simpler to change your selector to form:not([allowFormChangesLoss])
. Then you just need to import the module to your shared module, and all your already created forms will have this functionality. In case you want to disable it on a specific form, you can use <form allowFormChangesLoss>
, thus inversing the "default" behavior.