0

I am following link from : https://www.concretepage.com/angular-2/angular-candeactivate-guard-example and nothing is working for me in my real world application. I have below code.

AppModule

@NgModule({
  declarations: [
    AppComponent,
    TemplateComponent,
    HeaderComponent,
    FooterComponent,
    SidebarComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    AppRoutingModule,
    FormsModule
  ],
  providers: [DirectAccessGuard, PendingChangesGuard, DialogService],
  bootstrap: [AppComponent]
})
export class AppModule { }

DialogService

import { Injectable } from '@angular/core';
import 'rxjs/add/observable/of';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class DialogService {

  confirm(message?: string): Observable<boolean> {
    const confirmation = window.confirm(message || 'Are you sure?');

    return Observable.of(confirmation);
  }
}

AppRoutingModule

const routes: Routes = [
  {
    path: '',
    component: SidebarPageLayoutComponent,
    children: [
      ..........
      ..........
      {
        path: 'employee/:programId',
        canActivate: [DirectAccessGuard],
        canDeactivate: [PendingChangesGuard],
        pathMatch: 'full',
        loadChildren: './employee/employee.module#EmployeeModule'
      },
      ......
      .........
    ]
  }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

PendingChangesGuard

import { CanDeactivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Injectable, HostListener } from '@angular/core';
import { Observable } from 'rxjs';
import { ProgramComponent } from '../employee/employee.component';
import { DialogService } from '../services/dialog.service';

export interface ComponentCanDeactivate {
  canDeactivate: () => boolean | Observable<boolean>;
}

@Injectable()
export class PendingChangesGuard implements CanDeactivate<EmployeeComponent> {

  constructor(private dialogService: DialogService) { }

  canDeactivate(component: EmployeeComponent, route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | boolean {
    const url: string = state.url;
    console.log('Url: ' + url);

    if (!component.isUpdating && component.form.dirty) {
      component.isUpdating = false;
      return this.dialogService.confirm('Discard changes for Country?');
    }
    return true;
  }
}

NOTE: I am using Template Driven Forms and PendingChangesGuard class's method canDeactivate(component: CanComponentDeactivate...) where component variable is always coming null

PAA
  • 1
  • 46
  • 174
  • 282

2 Answers2

2

If you want to implement guard to lazyload module use canLoad Instead of canActivate.

Then Try moving CanDeactive inside EmployeeModule routes configuration.

employeeModule.routes.ts

const routes: Routes = [ {
        path: '',
        componenent: EmployeeComponent,
        canDeactivate: [PendingChangesGuard],
 }]
Chellappan வ
  • 23,645
  • 3
  • 29
  • 60
  • Sorry I am not clear with you code.I want to show alter in case if user did some update and without saving data, trying to move to different page – PAA Oct 04 '19 at 17:09
  • Can you share employeemodule route config as well? – Chellappan வ Oct 04 '19 at 17:11
  • If you try to move EmployeeComponent to another page your candeactivate will be triggered. So instead of providing canDeactive to module level provide canDeactive to component level – Chellappan வ Oct 04 '19 at 17:14
  • As per link: https://github.com/angular/angular/issues/16868 it seem some issue with LazyLoading. Also, EmployeeComponent moved out to another page ? What are you trying to say ? – PAA Oct 04 '19 at 17:19
  • Lazy Loading always showing component details as null when working with lazy loading – PAA Oct 04 '19 at 17:20
  • This looks useful: https://alligator.io/angular/route-guards/, but still not working for me – PAA Oct 04 '19 at 17:21
  • This is bug : https://github.com/angular/angular/issues/28730 – PAA Oct 04 '19 at 17:25
  • You want to trigger CanDeactivate when you want to navigate from employee module to some other page right? – Chellappan வ Oct 04 '19 at 17:25
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/200409/discussion-between-paa-and-chellappan). – PAA Oct 04 '19 at 17:25
0
  1. In the best practices, so that the guard can be used in any component, the Guard class PendingChangesGuard, should implement the interface not the component. Here, the interface is ComponentCanDeactivate:

    PendingChangesGuard
    export class PendingChangesGuard implements CanDeactivate<ComponentCanDeactivate>

  2. The component Module SidebarPageLayoutComponent.module.ts should declare the Guard in two places:

    SidebarPageLayoutComponent.module.ts

    const routes: Routes = [ { path: '...', component: SidebarPageLayoutComponent, canDeactivate: [PendingChangesGuard] } ]; @NgModule({ imports: [ ..., RouterModule.forChild(routes) ], declarations: [SidebarPageLayoutComponent], providers: [PendingChangesGuard] }) export class SidebarPageLayoutComponentModule { }

Ghazi
  • 1
  • 1
  • 2
    Please add some explanation to your answer such that others can learn from it – Nico Haase Apr 20 '20 at 13:49
  • my case is aslo same but thhe solution given here is not working can any one help me if you want i can post a new Question – Ram Sep 29 '22 at 18:42