4

I've been trying to write a canDeactivate guard to check a saving state from an observable stream and work accordingly.

My service goes as this

import { Injectable } from '@angular/core';
import { ReplaySubject } from 'rxjs/ReplaySubject';

import { Observable } from 'rxjs/Observable';

@Injectable()
export class EditModelService {

  private savingModelDataSource = new ReplaySubject<boolean>();

  savingModelData$ = this.savingModelDataSource.asObservable();

  public setSavingModelData(state: boolean) {
    this.savingModelDataSource.next(state);
  }

}

My guard goes as

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

import { Observable } from 'rxjs/Observable';

import { EditModelService } from './edit-model.service';

@Injectable()
export class EditModelCanDeactivateGuardGuard {
  private savingState: boolean;

  constructor(
    private editModelService: EditModelService
  ) { }

  CanDeactivate(
    currentRoute: ActivatedRouteSnapshot,
    currentState: RouterStateSnapshot
  ): Observable<boolean> | Promise<boolean> | boolean {

    this.editModelService.savingModelData$.subscribe(saving => {
      this.savingState = saving;
    });


    if (this.savingState) {
      return this.editModelService.savingModelData$.first();
    } else {
      return this.editModelService.savingModelData$.first();
    }

  }
}

Basically, it takes the value of the savingState from the service and returns according to the state so the router's canDeactivate attribute receives a boolean. Since the value this.savingState in the guard is always subscribed I don't think there is an issue with the conditional goes below.

With some search I came across this answer and tried doing the guard code as

return this.editModelService.savingModelData$.first();

Of course, I've imported first() here as import 'rxjs/add/operator/first';.

It returns an observable from the guard just to see whether that is working fine or if that is something to do with the way I am returning. But, in both of the scenarios, I get the error as shown in the image below.

enter image description here

I've provided the router guard inside the module where the router configuration is imported. That's where the service is provided as well.

What am I doing here wrong? I am new to using router guards(especially, canDeactivate with an observable) and any help is appreciated.

Saiyaff Farouk
  • 5,103
  • 4
  • 24
  • 38

1 Answers1

2

Your Guard Service must implement function to fully implement that CanActivate or CanDeactivate interface. Try changing as

From

@Injectable()
export class EditModelCanDeactivateGuardGuard {

To

@Injectable()
export class EditModelCanDeactivateGuardGuard  implements CanActivate, CanDeactivate<boolean>{

also your CanDeactivate should be changed to canDeactivate

 canDeactivate() {

 }

Updated after trying out the solution:

Also, change

From

canDeactivate(
    currentRoute: ActivatedRouteSnapshot,
    currentState: RouterStateSnapshot
): Observable<boolean> | Promise<boolean> | boolean ...

To

canDeactivate(): Observable<boolean> | Promise<boolean> | boolean...
Saiyaff Farouk
  • 5,103
  • 4
  • 24
  • 38
Sajeetharan
  • 216,225
  • 63
  • 350
  • 396
  • 1
    My bad. I had to remove the `currentRoute: ActivatedRouteSnapshot` `currentState: RouterStateSnapshot` parsed to `canDeactivate()`. Now it works fine. Thanks a million man! – Saiyaff Farouk Feb 28 '18 at 12:49