Angular CanDeactivate Guard递归触发,无法导航到组件

问题描述

要求:从当前组件(ProductsComponent)导航到不同组件(UsersComponent)时向用户显示确认模式。如果用户希望离开,则必须导航到其他组件(SalesComponent)而不是UsersComponent。 / p>

为实现上述目的,我在ProductsComponent中的canDeactivate()中返回了Subject。当用户确认在主题中保留发射UrlTree(salesComponent路径)但其触发可以递归停用并最终多次显示模式时。

任何想法如何解决?或通过使用CanDeactivate Guard,如何导航到用户预期之外的其他组件?

app-routing.module.ts

const routes:Routes = [
  {path: 'users',component: UsersComponent},{path: 'products',component: ProductsComponent,canDeactivate:[CanExitGuard]},{path: 'sales',component: SalesComponent}
];

can-exit.guard.ts

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

export interface CanComponentDeactivate {
  canDeactivate: () => boolean | UrlTree | Observable<boolean | UrlTree> | Promise<boolean | UrlTree>;
}

@Injectable({ providedIn: 'root' })
export class CanExitGuard implements CanDeactivate<CanComponentDeactivate> {


  canDeactivate(component: CanComponentDeactivate,currentRoute: ActivatedRouteSnapshot,currentState: RouterStateSnapshot,nextState?: RouterStateSnapshot): boolean | UrlTree | Observable<boolean | UrlTree> | Promise<boolean | UrlTree> {

         return component.canDeactivate ? component.canDeactivate() : true;
  }

}

products.component.ts ,请注意,我使用了“超时并确认”对话框来模拟异步操作。

import { Component,OnInit } from '@angular/core';
import { CanComponentDeactivate } from '../can-exit.guard';
import { Router,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<boolean | UrlTree> = new Subject();

  constructor(private router: Router) { }

  ngOnInit() {
  }

  canDeactivate() {
  console.log('Can Deactivate triggered...');
  const isConfirmed: boolean = confirm("Do you want to leave products? Ok - Takes to sales page");
//simulate asynchronous
setTimeout(()=>{
  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$;
}
}

StackBlitz Link

解决方法

您可以通过添加其他检查来解决此问题:

canDeactivate(
  component: CanComponentDeactivate,currentRoute: ActivatedRouteSnapshot,currentState: RouterStateSnapshot,nextState?: RouterStateSnapshot
): boolean | UrlTree | Observable<boolean | UrlTree> | Promise<boolean | UrlTree> {
  return component.canDeactivate && nextState.url === '/users' ? component.canDeactivate() : true;
}

您要确保仅当从/products导航到/users时才显示模式。

StackBlitz

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...