如何在组件中添加CanDeactivate功能?

时间:2018-08-27 17:30:44

标签: javascript angular

我正在尝试在组件中添加CanDeactivate功能。我有一个 有one input字段和按钮的表单。我想如果用户在输入字段中输入内容并移至下一个screen而不提交,则会显示一个对话框。如果用户从对话框框输入yes,则转到下一个组件,否则它将保持不变屏幕。

这是我的代码 https://stackblitz.com/edit/angular-ctwnid?file=src%2Fapp%2Fhello.component.ts

import {CanDeactivate} from '@angular/router';
import { HelloComponent } from './hello.component';

export default class DeactivateGuard implements CanDeactivate<HelloComponent> {

  canDeactivate(component: HelloComponent): boolean {

    if (!component.canDeactivate()) {
      if (confirm('You have unsaved changes! If you leave, your changes will be lost.')) {
        return true;
      } else {
        return false;
      }
    }
    return true;
  }

}

当前,当我在input字段中键入内容并单击next按钮时,它给我错误

ERROR
Error: Uncaught (in promise): TypeError: Cannot read property 'ngInjectableDef' of undefined
TypeError: Cannot read property 'ngInjectableDef' of undefined
at resolveNgModuleDep (https://angular-ctwnid.stackblitz.io/turbo_modules/@angular/core@6.0.0/bundles/core.umd.js:9309:31)
at NgModuleRef_.get (https://angular-ctwnid.stackblitz.io/turbo_modules/@angular/core@6.0.0/bundles/core.umd.js:10003:16)
at PreActivation.getToken (https://angular-ctwnid.stackblitz.io/turbo_modules/@angular/router@6.0.0/bundles/router.umd.js:3014:25)
at MergeMapSubscriber.eval [as project] (https://angular-ctwnid.stackblit

2 个答案:

答案 0 :(得分:0)

我认为理想的实现方法是创建一个接口,使Guard可以重用。

方法如下:

import { Injectable } from '@angular/core';
import { CanDeactivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';

export interface CanComponentDeactivate {
  confirm(): boolean;
}

@Injectable()
export class DeactivateGuard implements CanDeactivate < CanComponentDeactivate > {
  canDeactivate(
    component: CanComponentDeactivate,
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): boolean {
    if (!component.confirm()) {
      return confirm('You have unsaved changes! If you leave, your changes will be lost.');
    }
  }
}

然后,应在必须放置此防护罩的组件上实现此CanComponentDeactivate接口。这就是强制执行confirm方法的方法,从该方法中,返回的布尔值就是您要在后卫的canDeactivate方法中检查的值。

与此类似:

import { Component, Input } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { CanComponentDeactivate } from './deactivate.guard';

@Component({
  selector: 'hello',
  template: `<h1>Hello {{name}}!</h1>
      <form novalidate [formGroup]="sfrm" class="calform">
      <input type="text" formControlName="name"/>
      <button type="submit">submit</button>
      </form>
      <a [routerLink]="['/next']">next</a>
  `,
  styles: [`h1 { font-family: Lato; }`]
})
export class HelloComponent implements CanComponentDeactivate {
  @Input() name: string;
  sfrm: FormGroup

  constructor(private fb: FormBuilder) {
    this.sfrm = this.fb.group({
      name: ['']
    });
  }

  confirm() {
    return this.sfrm.submitted || !this.sfrm.dirty;
  }

}

最后一件事情是将Guard作为提供者添加。毕竟,这是一项服务。因此,将其添加到providers数组中:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { RouterModule, Routes } from '@angular/router';

import { ReactiveFormsModule } from '@angular/forms';

import { AppComponent } from './app.component';
import { HelloComponent } from './hello.component';
import { ErrorComponent } from './error.component';
import { DeactivateGuard } from './deactivate.gaurd';

import { TestService } from './test.service';
import { TestResolver } from './test.resolver';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { NextComponent } from './next/next.component';
const routes: Routes = [{
    path: 'home',
    component: HelloComponent,
    canDeactivate: [DeactivateGuard]
  },
  {
    path: 'next',
    component: NextComponent
  },
  {
    path: '',
    redirectTo: '/home',
    pathMatch: 'full'
  }
];
@NgModule({
  imports: [
    BrowserModule,
    ReactiveFormsModule,
    RouterModule.forRoot(routes),
    HttpClientModule, 
    FormsModule
  ],
  declarations: [
    AppComponent,
    HelloComponent, 
    ErrorComponent, 
    NextComponent
  ],
  bootstrap: [AppComponent],
  providers: [
    TestService, 
    TestResolver, 
    DeactivateGuard
  ]
})
export class AppModule {}

这应该使警卫为您工作。这是您的Updated StackBlitz

答案 1 :(得分:0)

您尚未在app.module.ts的提供程序中通过停用保护器,尚未编辑stackbiltz

     providers: [TestService,TestResolver,DeactivateGuard  
  ]