2016-12-14 10 views
5

Stworzyłem CanDeactivate guard, która zwraca obserwowalne i jest stosowane do komponentu, który jest załadowany w wewnętrznym zagnieżdżonym routerze. Czy ten strażnik powinien zostać wywołany za każdym razem, gdy próbuje się przejść do innego adresu URL? Pytam o to, ponieważ tak się nie dzieje w moim przypadku.angle2: CanDeactivate guard

W moim przypadku strażnik zostanie wezwany tylko na pierwszy "inny" URL. Pozwól, że spróbuję wyjaśnić to na przykładzie. Przyjmijmy, mam zawsze wraca fałszywe i próbuję nawigować do różnych adresów URL z tego samego komponentu:

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

Czy to jest normalne zachowanie?

edytuj Wygląda na to, że tak. Właśnie zbudowaliśmy małą próbkę z 3 komponentami, a strażnik zostanie wywołany tylko po raz pierwszy, gdy użytkownik spróbuje przejść do określonego adresu URL ... to jest naprawdę dziwne ...

W każdym razie, oto kod I ' m z:

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

Wszystko generowane przez skośne CLI (np .: ng składnika XXX). Tak, CanDeactivate guard zawsze zwróci false, więc nie będzie można zwolnić głównego komponentu. Tak więc, kiedy pierwszy raz kliknę drugi, strażnik zostaje wezwany. Jeśli klikniesz ponownie na innym, nie zostanie wywołana żadna straż. Jednakże, jeśli kliknę na inny3, zostanie wywołany strażnik. Kliknięcie na inne 3 nie zrobi niczego, dopóki nie kliknę na inny link (np .: inny) ...

Czy to oczekiwane zachowanie? Muszę powiedzieć, że spodziewałem się, że mój strażnik zostanie trafiony za każdym razem, gdy uderzę w inny link ...

Dzięki.

Luis

Odpowiedz

8

znalazłem to rozwiązanie, zamiast tworzyć osłonę candeactivate dla każdego komponent, utworzysz jedną usługę straży i dodasz metodę candeactivate do każdego komponentu, który chcesz dodać tę opcję, więc najpierw musisz dodać ten plik usługi "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; 
    } 
} 

potem trzeba dostarczyć w module aplikacji:

providers: [ 
    DeactivateGuardService 
    ] 

teraz w składniku, który chcesz chronić, dodać funkcję:

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

widać, że zmienna ładowanie jest lokalny składnik. Ostatnim krokiem jest dodanie dyrektywy do elementu w module routingu:

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

i to wszystko, mam nadzieję, że to był pomocny, goodluck.

+0

to działało dobrze dla mnie, dzięki! – NubbyMcNuberson

+0

Dzięki, bardzo fajne rozwiązanie. –

+0

Mam prawie dokładnie ten sam kod, ale dzwoniąc do strażnika, narzeka, że ​​komponent jest niezdefiniowany. W moim komponencie zaimportuję interfejs, klasa go zaimplementuje, a metoda zwróci wartość logiczną. W jaki sposób metoda "disactivateGuardService'" canDeactivate "pobiera komponent? – redOctober13

Powiązane problemy