3

I wanna add dialog window, with yes and no answers, after we click on router link, and if chose yes, we pass canActivate guard.

But after we change route and come buck to that router with guard again, us state will bee saved and no matter what we chose in dialog window, and we may pass guard before we chose answer in dialog window. How fix that?

guard service

import { Injectable } from '@angular/core';
import {AuthService} from './auth.service';
import {ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot} from '@angular/router';
import {DialogWindowComponent} from '../../Components/DialogWindow/dialog-window.component';
import {MatDialog} from '@angular/material/dialog';

@Injectable({
  providedIn: 'root'
})
export class AuthGuardService implements CanActivate{
    result: boolean;
    constructor(public dialog: MatDialog) {}

    openDialog(): void {
        const dialogRef = this.dialog.open(DialogWindowComponent, {
            width: '250px',
        });

        dialogRef.afterClosed().subscribe(result => {
            console.log('The dialog was closed');
            console.log(result);
            this.result = result;
        });
    }

    canActivate(
        next: ActivatedRouteSnapshot,
        state: RouterStateSnapshot): boolean {
        this.openDialog();
        console.log('AuthGuard#canActivate called');
        return this.result;
    }
}
Drop
  • 1,394
  • 3
  • 15
  • 25

1 Answers1

2

You also will not be able to return result that fashion from inside subscribe(). See the following related question regarding this issue.

That being said, try instead instead returning an Observable<boolean> as CanActivate can also return Observable<boolean> for these types of async operations:

import { Injectable } from '@angular/core';
import { AuthService } from './auth.service';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
import { DialogWindowComponent } from '../../Components/DialogWindow/dialog-window.component';
import { MatDialog } from '@angular/material/dialog';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class AuthGuardService implements CanActivate {
    constructor(public dialog: MatDialog) {}

    openDialog(): Observable<boolean> {
        const dialogRef = this.dialog.open(DialogWindowComponent, {
            width: '250px',
        });

        return dialogRef.afterClosed().pipe(map(result => {
          // can manipulate result here as needed, if needed
          // may need to coerce into an actual boolean depending
          return result;
        }));
    }

    canActivate(
        next: ActivatedRouteSnapshot,
        state: RouterStateSnapshot): Observable<boolean> {
        return this.openDialog();
    }
}

Hopefully that helps!

Alexander Staroselsky
  • 37,209
  • 15
  • 79
  • 91
  • Thanks, its work! How guard wait return from openDialog? I mean, we click on link and open modal and what happening next? – Drop Mar 16 '19 at 20:56
  • Effectively Angular is waiting for the `Observable` to resolve/emit before continuing navigation, which in this situation is when the modal is closed in some fashion. It's up to you to make sure that the result returned from `return dialogRef.afterClosed().pipe(map(` is the proper `true` or `false` value. `true` will allow navigation to continue, `false` will prevent navigation. – Alexander Staroselsky Mar 16 '19 at 20:57