2016-12-14 16 views
5

Tôi đã tạo ra một bảo vệ CanDeactivate trả về một quan sát và nó được áp dụng cho một thành phần được tải trong một bộ định tuyến lồng nhau bên trong. Bảo vệ này có nên được gọi bất cứ khi nào một người cố gắng điều hướng đến một url khác không? Tôi hỏi điều này bởi vì điều này không xảy ra trong trường hợp của tôi.angular2: CanDeactivate guard

Trong trường hợp của tôi, người bảo vệ sẽ chỉ được gọi cho URL "khác" đầu tiên. Hãy để tôi cố gắng giải thích nó với một ví dụ. Giả sử tôi luôn trả về false và tôi đang cố điều hướng đến các url khác nhau từ cùng một thành phần:

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

Đây có phải là hành vi mong đợi không?

chỉnh sửa Vâng, có vẻ như vậy. Vừa xây dựng một mẫu nhỏ với 3 thành phần và bảo vệ sẽ chỉ được gọi cho lần đầu tiên người dùng cố gắng điều hướng đến một địa chỉ cụ thể ... điều này thực sự lạ ...

Anyways, đây là mã tôi ' Tôi đang sử dụng:

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

Mọi thứ đã được tạo ra thông qua góc-cli (ví dụ .: ng thành phần XXX). Có, trình bảo vệ CanDeactivate sẽ luôn trả về false vì vậy bạn sẽ không thể dỡ bỏ thành phần chính. Vì vậy, lần đầu tiên tôi bấm vào khác, bảo vệ được gọi. Nếu nhấp một lần nữa trên khác, không có bảo vệ được gọi. Tuy nhiên, nếu tôi nhấp vào khác3, sau đó bảo vệ được gọi. Nhấp vào khác3 sẽ không thực sự làm gì cho đến khi tôi nhấp vào liên kết khác (ví dụ: khác) ...

Đây có phải là hành vi mong đợi không? Tôi phải nói rằng tôi mong đợi bảo vệ của mình bị đánh trúng mỗi lần tôi nhấn vào một liên kết khác ...

Cảm ơn.

Luis

Trả lời

8

tôi đã tìm được giải pháp này, thay vì tạo một người bảo vệ candeactivate cho mỗi thành phần, bạn sẽ tạo một dịch vụ bảo vệ và thêm phương thức kích hoạt cho mọi thành phần bạn muốn thêm tùy chọn này, vì vậy trước tiên bạn phải thêm tệp dịch vụ này "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; 
    } 
} 

sau đó bạn phải cung cấp trong các module ứng dụng:

providers: [ 
    DeactivateGuardService 
    ] 

bây giờ trong thành phần bạn muốn bảo vệ, thêm chức năng:

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

bạn có thể thấy rằng việc bốc biến là địa phương để thanh phân. bước cuối cùng là thêm các chỉ thị để các thành phần trong module định tuyến:

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

và thats nó, tôi hy vọng điều này là hữu ích, goodluck.

+0

điều này làm việc tốt cho tôi, cảm ơn! – NubbyMcNuberson

+0

Cảm ơn, giải pháp rất tốt đẹp. –

+0

Tôi có gần như cùng một mã, nhưng khi gọi bảo vệ, nó phàn nàn rằng thành phần là không xác định. Trong thành phần của tôi, tôi đang nhập giao diện, lớp thực hiện nó và phương thức trả về một boolean. Phương thức 'canDeactivate' của' DeactivateGuardService' lấy thành phần như thế nào? – redOctober13

Các vấn đề liên quan