admin管理员组

文章数量:1406951

I am trying to add CanDeactivate functionality in my ponent.I have a form in which there is one input field and button. i want if user enter something in input field and move to next screen without submit it will show a dialog box .if user enter yes from the dialog bix then it go to next ponent else it remain in same screen .

here is my code ponent.ts

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

export default class DeactivateGuard implements CanDeactivate<HelloComponent> {

  canDeactivate(ponent: HelloComponent): boolean {

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

}

currently when I am typing something on input field and click next button it give me error

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

I am trying to add CanDeactivate functionality in my ponent.I have a form in which there is one input field and button. i want if user enter something in input field and move to next screen without submit it will show a dialog box .if user enter yes from the dialog bix then it go to next ponent else it remain in same screen .

here is my code https://stackblitz./edit/angular-ctwnid?file=src%2Fapp%2Fhello.ponent.ts

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

export default class DeactivateGuard implements CanDeactivate<HelloComponent> {

  canDeactivate(ponent: HelloComponent): boolean {

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

}

currently when I am typing something on input field and click next button it give me error

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/[email protected]/bundles/core.umd.js:9309:31)
at NgModuleRef_.get (https://angular-ctwnid.stackblitz.io/turbo_modules/@angular/[email protected]/bundles/core.umd.js:10003:16)
at PreActivation.getToken (https://angular-ctwnid.stackblitz.io/turbo_modules/@angular/[email protected]/bundles/router.umd.js:3014:25)
at MergeMapSubscriber.eval [as project] (https://angular-ctwnid.stackblit
Share edited Aug 27, 2018 at 18:09 James 22.4k5 gold badges29 silver badges43 bronze badges asked Aug 27, 2018 at 17:30 user944513user944513 12.8k52 gold badges185 silver badges348 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 5

I think an ideal implementation would be to create an interface that would allow the Guard to be reusable.

Here's how:

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(
    ponent: CanComponentDeactivate,
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): boolean {
    if (!ponent.confirm()) {
      return confirm('You have unsaved changes! If you leave, your changes will be lost.');
    }
  }
}

Then this CanComponentDeactivate Interface should be implemented the ponent on which you have to place this guard. That's how it would be forced to implement the confirm method from where the returned boolean value is what you'd want to check in the canDeactivate method of your guard.

Something along the lines of this:

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

}

One final thing would be to also add the Guard as a provider. After all, it's a service. So add it to the providers array:

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

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

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

import { TestService } from './test.service';
import { TestResolver } from './test.resolver';
import { HTTP_INTERCEPTORS } from '@angular/mon/http';
import { NextComponent } from './next/next.ponent';
const routes: Routes = [{
    path: 'home',
    ponent: HelloComponent,
    canDeactivate: [DeactivateGuard]
  },
  {
    path: 'next',
    ponent: 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 {}

This should make the guard work for you. Here's your Updated StackBlitz

you have not passed the deactivae guard in providers on app.module.ts , edited your stackbiltz

     providers: [TestService,TestResolver,DeactivateGuard  
  ]

本文标签: javascripthow to add CanDeactivate functionality in componentStack Overflow