1

感谢您花时间在这里。

所以我对canDeactivate没有什么问题。我做了一个页面如果我点击返回按钮,将会出现一个模式,用户可以选择是否退出该页面。如果我只点击一次,效果很好。但问题就在这里。假设我位于 [page A -> page B -> page C] 并且在页面 C 上,我放置了 canDeactivate。因此,如果我在单击返回时单击模态上的确定,它会很好地移动到页面 B。但是,如果我先在 Modal 上单击 Cancel 并再次单击 go-back,当我单击 Ok 时,它会移动到页面 A。当然,每当我调用 canDeactivate 时,无论我在 modal 上单击什么,它都会像它已经移动一样。

所以我想做的就是无论我调用canDeactivate多少次,当我在模态上单击“确定”时,我想移动到页面B。希望你们都有我的解决方案。

canDeactivate.文件

export class DeactiveGuard implements CanDeactivate<GrammarComponent> {
  constructor(private router: Router) {}
  canDeactivate(component: GrammarComponent) {  
    return component.canDeactivate ? component.canDeactivate() : true 
  }
}

页 C. 文件

  public canDeactivate() {
    if (!this.exceptCanDeactivate) {
      return from(
        this.modalService.open(this.exitFromExamMd, {
          centered: true,
          scrollable: true,
          windowClass: 'final-confirm',
        }).result,
      ).pipe(map((result) => result === 'yes'))
    } else {
      return true
    }
  }
4

1 回答 1

1

根据Angular 文档canDeactivate守卫可以返回,除其他外, an UrlTree, anObservable<UrlTree>甚至 a Promise<UrlTree>。AUrlTree是一种导航到您想要的任何地方的方法。当你指定命运时,无论你点击哪里离开,你总是会被重定向到相同的命运。

这就是你可以做的:在你的守卫中,返回一个 observable,它在内部会在你关闭对话框时发出(在这个例子中,我假设一个异步确认对话框 API,就像我们在 @angular/material 对话框中所做的那样):

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

  constructor(private matDialog: MatDialog, private router: Router) {}

  canDeactivate(
    component: YourComponent,
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<UrlTree> {
    const observable = new Observable(observer => {
      const dialogRef = this.matDialog.open(YourConfirmationDialogComponent);
      dialogRef.afterClosed().subscribe((okButtonClicked) => {
          observer.next(this.router.parseUrl(urlString));
          observer.complete();
      });
    });

    return observable;
  }
}

在您的情况下,因为您使用的是 NgbModal:

  constructor(private modalService: ModalManager) {}

  canDeactivate(): Observable<UrlTree> {
    const observable = new Observable(observer => {
      const dialogRef = this.modalService.open(this.exitFromExamMd, {
          centered: true,
          scrollable: true,
          windowClass: 'final-confirm',
        });
      dialogRef.onClose.subscribe(() => {
          observer.next(this.router.parseUrl(urlString));
          observer.complete();
      });
    });

    return observable;
  }
于 2020-09-09T00:21:31.277 回答