Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Uncaught (in promise): TypeError: component.canDeactivate is not a function

I have this error when I build my CanDeactivateGuard .

Uncaught (in promise): TypeError: component.canDeactivate is not a function

I want to make my CanDeactivateGuard reusable, so it should be generic.

therefor I've built an abstract class which called ComponentCanDeactivate and then extended it in the TreeCanDeactivateGuard.

The CanDeactivateGuard should then implement the interface CanDeactivate.

My Code:

import { HostListener } from '@angular/core';

export abstract class ComponentCanDeactivate {

  public abstract canDeactivate(): boolean;

  @HostListener('window:beforeunload', ['$event'])
  unloadNotification($event: any) {
    if (!this.canDeactivate()) {
        $event.returnValue = true;
    }
}

}

The TreeCanDeactivateGuard :

import { ComponentCanDeactivate } from './canDeactivate/component-can-deactivate';
import { NodeService } from '../tree/node.service';


export abstract class TreeCanDeactivateGuard extends ComponentCanDeactivate {

    constructor(private _nodeService: NodeService) {
    super();
    }

    public canDeactivate(): boolean {
      if (this._nodeService.treeChangesTracer === false) {
          return true;
       } else {
          return false;
      }
}

}

The CanDeactivateGuard:

   import { Injectable } from '@angular/core';
    import { CanDeactivate } from '@angular/router';
    import { ComponentCanDeactivate } from './component-can-deactivate';

    @Injectable()
    export class CanDeactivateGuard implements CanDeactivate<ComponentCanDeactivate> {

        constructor() { }
         canDeactivate(component: ComponentCanDeactivate): 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;
        }
    }

Routes Module :

const routes: Routes = [
{
    path: '', component: TreeComponent, canDeactivate: [CanDeactivateGuard] , runGuardsAndResolvers: 'always',
}]
like image 537
Taher Avatar asked Dec 20 '18 14:12

Taher


1 Answers

What is TreeCanDeactivateGuard? It isn't referenced anywhere in your code.

You don't want TreeCanDeactivateGuard to extend ComponentCanDeactivate, you want TreeComponent to extend ComponentCanDeactivate instead.

Make any component extend ComponentCanDeactivate and implement canDeactivate then you'll be able to use the generic guard CanDeactivateGuard for it.

You could also replace:

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

With: return confirm('You have unsaved changes! If you leave, your changes will be lost.');

like image 145
Guerric P Avatar answered Sep 17 '22 14:09

Guerric P