typescript - Hvordan skrive en guard for å hindre at en bruker mister skjema-data i Angular 6?


Jeg ønsker å lage en vakt i Angular 6-appen min som vil hindre en bruker i å navigere bort fra skjemaet på nettstedet (ikke ved å lukke nettleseren eller oppdatere) fra et delvis utfylt skjema ved å be dem bekrefte først.

Hvordan kan jeg bygge min vakt slik at jeg kan bruke den på rutene mine og hindre brukeren i å ved et uhell navigere bort fra et urent skjema?

Jeg prøver å injisere skjemaet i vaktskomponenten, observere om det er endret eller ikke, og hvis det er det, bruke den vakten på hvilken som helst annen rute og få brukeren til å bekrefte før de navigerer til dem. Dette er så nært jeg kunne komme, all hjelp vil bli satt stor pris på.

Her er hva jeg har så langt:

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

I forms komponenten min har jeg dette, slik at skjemaobjektet kan importeres av vakten:

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

og rutene mine ser omtrent slik ut:

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

Svar #1

Det du ser etter er en CanDeactivate-vakt. Dette er en vakt som vil bli kalt før du navigerer bort fra en rute, og som får komponenten som den nåværende ruten har rendret.

Du kan implementere dette på en måte som dette:

interface FormComponent {
  hasUnsavedChanges: boolean
}

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

ref: https://angular.io/api/router/CanDeactivate

Relaterte artikler