title: Angular CanDeactivate Guard is triggering recursively and failing to navigate to the component
body: <p>Requirement: Showing a confirmation modal to the user when navigating to different component(UsersComponent) from the current component(ProductsComponent).If user prefers to leave, I have to navigate to some other component(SalesComponent) rather than UsersComponent.</p>
  <p>To achieve the above am returning a Subject in canDeactivate() present in ProductsComponent. when user confirms to leave am emitting UrlTree(salesComponent path) in subject but its triggering canDeactivate recursively and ending up showing the modal multiple times.</p>
  <p>Any Idea how to fix it ? or by using CanDeactivate guard how can I navigate to Other component than user intended?</p>
  <p><strong>app-routing.module.ts</strong></p>
  <pre><code>const routes:Routes = [
    {path: 'users', component: UsersComponent},
    {path: 'products', component: ProductsComponent, canDeactivate:[CanExitGuard]},
    {path: 'sales', component: SalesComponent}
  ];
  </code></pre>
  <p><strong>can-exit.guard.ts</strong></p>
  <pre><code>import { Injectable } from '@angular/core';
  import { CanDeactivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree } from '@angular/router';
  import { Observable } from 'rxjs';
  
  export interface CanComponentDeactivate {
    canDeactivate: () =&gt; boolean | UrlTree | Observable&lt;boolean | UrlTree&gt; | Promise&lt;boolean | UrlTree&gt;;
  }
  
  @Injectable({ providedIn: 'root' })
  export class CanExitGuard implements CanDeactivate&lt;CanComponentDeactivate&gt; {
  
  
    canDeactivate(component: CanComponentDeactivate,
                  currentRoute: ActivatedRouteSnapshot,
                  currentState: RouterStateSnapshot,
                  nextState?: RouterStateSnapshot): boolean | UrlTree | Observable&lt;boolean | UrlTree&gt; | Promise&lt;boolean | UrlTree&gt; {
  
           return component.canDeactivate ? component.canDeactivate() : true;
    }
  
  }
  </code></pre>
  <p><strong>products.component.ts</strong>, Please note I used Timeout and confirm dialog to simulate the asynchronous action.</p>
  <pre><code>import { Component, OnInit } from '@angular/core';
  import { CanComponentDeactivate } from '../can-exit.guard';
  import { Router,RouterStateSnapshot, UrlTree } from '@angular/router';
  import { Subject } from 'rxjs';
  
  @Component({
    selector: 'app-products',
    templateUrl: './products.component.html',
    styleUrls: ['./products.component.css']
  })
  export class ProductsComponent implements OnInit, CanComponentDeactivate {
  
  navigationSelection$: Subject&lt;boolean | UrlTree&gt; = new Subject();
  
    constructor(private router: Router) { }
  
    ngOnInit() {
    }
  
    canDeactivate() {
    console.log('Can Deactivate triggered...');
    const isConfirmed: boolean = confirm(&quot;Do you want to leave products? Ok - Takes to sales page&quot;);
  //simulate asynchronous
  setTimeout(()=&gt;{
    if(isConfirmed){
      console.log('navigates to sales page');
  
      const UrlTree: UrlTree = this.router.createUrlTree(['sales']);
      this.navigationSelection$.next(UrlTree);
    } else {
      console.log('navigation Canceled');
      this.navigationSelection$.next(false);
    }
  }, 7000);
  
    return this.navigationSelection$;
  }
  }
  </code></pre>
  <p><a href="https://stackblitz.com/edit/angular-candeactivate-4fb6uh?file=src/app/can-exit.guard.ts" rel="nofollow noreferrer">StackBlitz Link</a></p>