2016-12-14 3 views
5

ObDable을 반환하는 CanDeactivate 가드를 생성했으며 내부 중첩 된 라우터 콘센트에로드 된 구성 요소에 적용됩니다. 다른 URL로 이동하려고 할 때마다이 가드를 호출해야합니까? 나는 이것이 나의 경우에는 일어나지 않기 때문에 이것을 요구하고있다.angular2 : 가드를 CanDeactivate

필자의 경우 경비원은 첫 번째 "다른"URL에 대해서만 호출됩니다. 예를 들어 설명해 드리겠습니다. 저는 항상 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 

이것은 예상되는 동작입니까?

편집 글쎄, 그렇지 않은 것 같습니다. 3 개의 구성 요소가있는 작은 샘플을 만든 후 경비원이 처음으로 특정 URL로 이동하려고 시도 할 때만 호출됩니다 ... 이것은 정말로 이상합니다 ...

어쨌든, 사용 m :

// 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>

모두가 볼록 CLI (예 : 겨 성분 XXX)을 통해 생성 하였다. 예, CanDeactivate 가드는 항상 false를 반환하므로 주 구성 요소를 언로드 할 수 없습니다. 그래서 처음으로 다른 것을 클릭하면 가드가 호출됩니다. 다른 버튼을 다시 클릭하면 가드가 호출되지 않습니다. 그러나 other3을 클릭하면 경비원이 호출됩니다. other3을 클릭하면 실제로 다른 링크 (예 : 다른)를 클릭 할 때까지 아무런 효과가 없습니다 ...

예상되는 동작입니까? 나는 내 경비원이 다른 링크를 때릴 때마다 내 경비원이 타격을 가할 것이라고 예상해야한다고 말해야한다 ...

고마워.

루이스

답변

8

은 보드이 솔루션을 문제를 확인하는 대신 모든위한 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; 
    } 
} 

다음 앱 모듈에 제공해야합니다 : 가변 부하가 로컬 것을

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; 
    } 
} 

당신이 볼 수 있습니다 보호 할 구성 요소 지금

providers: [ 
    DeactivateGuardService 
    ] 

, 기능을 추가 구성 요소. 내가이, goodluck는 helpfull했다 희망,

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

과 이잖아 : 마지막 단계는 라우팅 모듈의 구성 요소에 지시문을 추가하는 것입니다.

+0

감사합니다. – NubbyMcNuberson

+0

고마워, 아주 좋은 해결책. –

+0

나는 거의 똑같은 코드를 가지고 있지만 가드를 호출 할 때 그 구성 요소가 정의되지 않았다는 불평을하고있다. 내 구성 요소에서 인터페이스를 가져오고 클래스가이를 구현하며 메서드는 부울을 반환합니다. 'DeactivateGuardService'의'canDeactivate' 메소드는 어떻게 구성 요소를 가져 옵니까? – redOctober13

관련 문제