I'm looking to create a guard in my Angular 6 app that will keep a using from navigating away from the form within the site (not through closing the browser or refreshing) from a partially filled out form by asking them to confirm first.
How can I build my guard so that I can apply it to my routes and keep the user from accidentally navigating away from a dirty form?
I'm trying to inject the form into the guard component, observe if it is dirty or not, and if it is, apply that guard to any other route and get the user to confirm before navigating to them. This is about as close as I could get, any help would be greatly appreciated.
Here's what I have so far:
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, CanDeactivate } from '@angular/router';
import { Observable } from 'rxjs';
import { NgForm } from "@angular/forms";
import { createMPForm } from "../components/site-settings/site-settings.component"
@Injectable({
providedIn: 'root'
})
@Injectable()
export abstract class FormGuard implements CanActivate {
abstract get form(): NgForm;
formDirty(): boolean {
return createMPForm.dirty
}
constructor() { }
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
if (this.formDirty()) {
if (confirm("You have unsaved changes! If you leave, your changes will be lost.")) {
return true;}
else {
return false;}
}
}
}
In my form component I have this, so that the form object can be imported by the guard:
export class createMPForm {
@ViewChild("createMPForm", {read: ElementRef}) form: ElementRef;
}
and my routes look something like this:
import { FormGuard } from './services/form-guard.service';
import { SiteSettingsComponent } from './components/site-settings/site-settings.component';
import { SiteComponent } from './components/site/site.component';
import { AuthGuard } from './services/auth-guard.service';
const routes: Routes = [
{ path: 'sites', component: SitesComponent, canActivate: [AuthGuard] }, //the route I want to keep from navigating to if the form is dirty
{ path: 'site-settings/:siteHid', component: SiteSettingsComponent, canActivate: [AuthGuard] }// the route with the form
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
providers: [AuthGuard, FormGuard]
})