简体   繁体   English

angular2:CanDeactivate guard

[英]angular2: CanDeactivate guard

I've created a CanDeactivate guard which returns an observable and it's applied to a component which is loaded in a inner nested router-outlet. 我创建了一个CanDeactivate防护,它返回一个observable,它应用于一个加载在内部嵌套路由器插座中的组件。 Should this guard be called whenever one tries to navigate to another url? 每当有人试图导航到另一个URL时,是否应该调用此警卫? I'm asking this because this is not happening in my case. 我问这个是因为我的情况并没有发生这种情况。

In my case, the guard will only get called for the first "different" URL. 在我的情况下,警卫只会被调用第一个“不同”的URL。 Let me try to explain it with an example. 让我试着用一个例子来解释它。 Assume I'm always returning false and I'm trying to navigate to different urls from the same component: 假设我总是返回false并且我试图从同一个组件导航到不同的url:

/A --> guard called
/B --> guard called
/B --> no navigation and no guard called
/A --> guard called
/A -->guard not called and no navigation

Is this the expected behavior? 这是预期的行为吗?

edit Well, it seems like it is. 编辑好吧,它似乎是。 Have just built a small sample with 3 components and the guard will only be called for the 1st time the user tries to navigate to a specific url...this is really weird... 刚刚建立了一个包含3个组件的小样本,只有在用户第一次尝试导航到特定网址时才会调用防护...这真的很奇怪......

Anyways, here's the code I'm using: 无论如何,这是我正在使用的代码:

// app.routing
import {NgModule} from "@angular/core";
import {Routes, RouterModule, Route, CanDeactivate, ActivatedRouteSnapshot, 
        RouterStateSnapshot} from "@angular/router";
import { MainComponent } from "./main/main.component";
import { OtherComponent } from "./other/other.component";
import { Other3Component } from "./other3/other3.component";
import {Observable} from "rxjs/observable";
const fallback: Route = {
    path: "**",
    redirectTo: "/main",
    pathMatch: "full"
};
export class Test implements CanDeactivate<MainComponent>{
  canDeactivate(component: MainComponent, route: ActivatedRouteSnapshot, 
            state: RouterStateSnapshot): Observable<boolean> | boolean{
    console.log("in");
    return false;
  }
}
export const rotas: Routes = [
{
    path: "main",
    component: MainComponent,
    canDeactivate: [Test]
},
{
    path: "other",
    component: OtherComponent
},
{
    path: "other3",
    component: Other3Component
},
fallback
];

@NgModule({
 imports: [RouterModule.forRoot(rotas)],
 exports: [RouterModule]
})
export class AppRoutingModule{}

//app.component.html <h1> <a routerLink="/main">Main</a> <a routerLink="/other">Other</a> <a routerLink="/other3">Other3</a> </h1> //app.component.html <h1> <a routerLink="/main">Main</a> <a routerLink="/other">Other</a> <a routerLink="/other3">Other3</a> </h1>

Everything was generated through angular-cli (ex.: ng component XXX). 一切都是通过angular-cli生成的(例如:ng组件XXX)。 Yes, the CanDeactivate guard will always return false so you won't be able to unload the main component. 是的,CanDeactivate后卫将始终返回false,因此您将无法卸载主要组件。 So, the first time I click other, the guard gets called. 所以,当我第一次点击其他时,警卫会被召唤。 If click again on other, no guard gets called. 如果再次点击其他,则不会调用任何警卫。 However, if I click over other3, then the guard gets called. 但是,如果我点击其他3,那么警卫就会被调用。 Clicking over other3 won't really do anything until I've clicked on other link (ex.: other)... 在我点击其他链接(例如:其他)之前点击其他3将不会真正做任何事情......

Is this the expected behavior? 这是预期的行为吗? I must say that I expected my guard to get hit everytime I hit another link... 我必须说,每当我点击另一个链接时,我都希望我的后卫能够被击中...

Thanks. 谢谢。

Luis 路易斯

i have found this solution, instead of creating a candeactivate guard for every component, you will create one guard service and add a candeactivate method to every component you want to add this option, so first you have to add this service file "deactivate-guard.service.ts": 我找到了这个解决方案,而不是为每个组件创建一个candeactivate防护,你将创建一个防护服务并为你想要添加此选项的每个组件添加一个candeactivate方法,所以首先你必须添加这个服务文件“deactivate-guard .service.ts“:

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

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

@Injectable()
export class DeactivateGuardService implements  CanDeactivate<CanComponentDeactivate>{

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

then you have to provide in the app module: 然后你必须在app模块中提供:

providers: [
    DeactivateGuardService
  ]

now in the component you want to protect, add the function: 现在在要保护的组件中,添加功能:

export class ExampleComponent {
    loading: boolean = false;
    //some behaviour that change the loading value
    canDeactivate() {
        console.log('i am navigating away');
        if (this.loading) {
            console.log('no, you wont navigate anywhere');
            return false;
        }
        console.log('you are going away, goodby');
        return true;
    }
}

you can see that the variable loading is local to the component. 您可以看到变量加载是组件的本地加载。 the final step is to add the directive to the component in the routing module: 最后一步是将指令添加到路由模块中的组件:

{ 
  path: 'example', 
  canDeactivate: [DeactivateGuardService],
  component: ExampleComponent 
}

and thats it, i hope this was helpfull, goodluck. 就是这样,我希望这很有帮助,祝你好运。

Damn, bug...Note to self: next time, check the issues board first 该死的,错误...自我注意:下次,先检查问题板

https://github.com/angular/angular/issues/12851#event-880719778 https://github.com/angular/angular/issues/12851#event-880719778

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 路线防护中的Angular 2对话框可以激活 - Angular 2 dialog in route guard candeactivate 访问can内的下一条路由信息在新的angular2路由器中停用防护 - Access next route information inside canDeactivate guard in new angular2 router Angular7:Global Guard-CanDeactivate界面 - Angular7: Global Guard - CanDeactivate interface Angular CanDeactivate Router Guard具有可观察的订阅值 - Angular CanDeactivate Router Guard with an Observable Subscribed Value CanDeactivate Guard中的Angular 2 Router 3.0未来路由 - Angular 2 Router 3.0 Future Route in CanDeactivate Guard Angular CanDeactivate Guard 不适用于 Sweet Alert JS - Angular CanDeactivate Guard not working with Sweet Alert JS Angular CanDeactivate Guard not working with MatDialog - Angular CanDeactivate Guard Not Working Properly With MatDialog Angular 6:如何注册 canDeactivate 防范所有路由 - Angular 6: How to register canDeactivate guard against all Routes Angular CanDeactivate Guard 递归触发并且无法导航到组件 - Angular CanDeactivate Guard is triggering recursively and failing to navigate to the component Angular 4初始页面加载可能会停用路由防护功能 - Angular 4 initial page load candeactivate route guard not working
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM