Angular 2 RC5获取canDeactivate中预期的路由

8
在Angular 2 RC5路由器的CanDeactivate守卫中,是否有可能获取预期路线?我看到了一个关于CanActivate的类似问题的答案(CanActivate),但在CanDeactivate守卫中似乎不起作用。
我的用例如下: 当用户在填写"FormComponent"处理的表单时,单击"Home"链接。 FormComponent附加了CanDeactivate。我需要知道用户是要去"Home"路线,以决定我希望在CanDeactivate中做什么。在CanDeactivate守卫中查看ActivatedRouteSnapshot和RouterStateSnapshot对象仅显示与FormComponent相关的用户当前所在路线的信息。虽然我明白这会将这两个组件耦合在一起,但这只是一个例子,以了解是否可能这样做。

Angular官方文档中的ActivatedRouteSnapshot,你可能正在canActivate函数中使用,包含root、parent和pathFromRoot属性,可以用来计算URL。https://angular.io/docs/ts/latest/api/router/index/ActivatedRouteSnapshot-interface.html - peppermcknight
我只能从当前活动的路由上获取ActivatedRouteSnapshot的信息,而不能从即将激活的路由上获取。 - ruk
2个回答

7

由于您可以向守卫中的CanDeactivate()返回Observable<boolean>,因此您可能不需要下一个路由的目标URL。

当我们检查守卫时,我们触发组件中更改的检查,并将过滤后的 Observable 返回给守卫。(仅将其过滤为“true”值-否则我们将无法继续导航到所需的路由!)

当我们的检查通过时,我们可以导航-如果不行,则不能。

因此,我们可能想向用户显示两个按钮。 一个用于跳过保存并导航(doNotSaveAndNavigate()),另一个用于保存并继续导航(doSaveAndNavigate())...或任何其他帮助来指导他或她..

some.component.ts

import { Component } from '@angular/core';

// Utils
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Observable }      from 'rxjs/Observable';

@Component({
  selector: 'selector',
  templateUrl: 'some.component.html'
})
export class SomeComponent {
  // Utils
  youMayNavigateSource = new BehaviorSubject<boolean>(false);
  youMayNavigate$: Observable<boolean> = this.youMayNavigateSource.asObservable();

  checkForUnsavedChanges(): void {
    // Check your form/data for changes...
    let hasSaved: boolean = false;
    // Set the next value for our observable
    this.youMayNavigateSource.next(hasSaved);
  }

  canDeactivate(): Observable<boolean> {
    // Do some checking if we "can deactivate" the current route 
    this.checkForUnsavedChanges();
    // Return an observable so we can change it later on and continue our navigation attempt
    return this.youMayNavigate$.filter(el => el); // (!)
  }

  allowNavigation(): void {
    // Set the next value for our observable to true
    this.youMayNavigateSource.next(true);
  }

  doNotSaveAndNavigate(): void {
    this.allowNavigation();
  }

  doSaveAndNavigate(): void {
    // Save our data
    this.doSave();
    this.allowNavigation();
  }

  doSave(): void {
    // do some fancy saving...
  }
}

can-deactivate-guard.service.ts

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

import { SomeComponent } from './some.component';

@Injectable()
export class CanDeactivateGuard implements CanDeactivate<SomeComponent > {
  canDeactivate(component: SomeComponent ) {
    return component.canDeactivate ? component.canDeactivate() : true;
  }
}

我猜你知道如何为路由设置CanDeactivate,但为了完整起见,你可以在官方文档中找到一个使用示例。


提示:如果您只想在CanDeactivate()失败时获取URL,请订阅router.events并过滤NavigationCancel事件,如下所示:

this.router.events
           .filter(event => event instanceof NavigationCancel)
           .subscribe(el => console.log('Requested URL:', el.url));

您可能需要导入:

import { Router, NavigationCancel } from '@angular/router'; 
import 'rxjs/add/operator/filter';

并将router添加到您的构造函数中:
  constructor(private router: Router) { }

如果有人想知道为什么.filter会抛出错误-你必须使用.pipe()与它一起使用。 - gfels

5

Angular 4引入了CanDeactivate接口的一个额外可选参数。

您可以在这里看到它。

    canDeactivate(
      component: T, 
      currentRoute: ActivatedRouteSnapshot,
      currentState: RouterStateSnapshot, 
      nextState?: RouterStateSnapshot
      ): Observable<boolean>|Promise<boolean>|boolean;

您可以将其与Observable、Promise或立即返回布尔值一起使用。
例如:
      canDeactivate(
        component: RetailerComponent,
        route: ActivatedRouteSnapshot,
        currentState: RouterStateSnapshot,
        nextState: RouterStateSnapshot
      ): Observable<boolean> | boolean {
        if (nextState.url.includes('company/manage'))
          return false;
        else
          return true;

这里有讨论相关问题的内容。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接