Angular6 中如何编写守卫以防止用户丢失表单数据?

How to write a guard to keep a user from losing form data in Angular 6?

我希望在我的 Angular 6 应用程序中创建一个保护程序,以防止用户从部分填写的内容中导航离开站点内的表单(不是通过关闭浏览器或刷新)通过要求他们先确认形成。

我如何建立我的守卫,以便我可以将它应用到我的路线,并防止用户意外地离开脏表单?

我正在尝试将表单注入守卫组件,观察它是否脏了,如果脏了,将该守卫应用到任何其他路由并让用户在导航到它们之前进行确认。这是我所能得到的最接近的,任何帮助将不胜感激。

这是我目前的情况:

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;}
    }
  }
}

在我的表单组件中我有这个,这样表单对象就可以被守卫导入:

export class createMPForm {
   @ViewChild("createMPForm", {read: ElementRef}) form: ElementRef;
 }

我的路线看起来像这样:

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]
})

您正在寻找的是 CanDeactivate 守卫。这是一个守卫,在离开路线之前将被调用,并提供当前路线已呈现的组件。

你可以这样实现:

interface FormComponent {
  hasUnsavedChanges: boolean
}

class FormGuard implements CanDeactivate<FormComponent> {
  canDeactivate(component: FormComponent) {
    return component.hasUnsavedChanges === false
  }
}

参考: https://angular.io/api/router/CanDeactivate