2016-01-10 5 views
10

В Угловом 2 вы можете указать аннотацию для компонента, в котором вы можете определить, должен ли компонент быть активирован или нет. Причина, по которой это не интерфейс, заключается в том, что обратный вызов вызывается до того, как компонент даже создается. Проблема в том, что я не могу найти способ получить зависимости, введенные в этот обратный вызов. И мне нужна моя служба, которая сообщает мне, вошел ли я в систему или нет (и как кто), чтобы определить, разрешена ли маршрутизация к определенному компоненту или нет.Угловой 2: Вложить зависимость в @CanActivate?

Как я могу вставить зависимость в обратный вызов @CanActivate? Я использую ES5, и это не работает:

app.ListsComponent = ng.router.CanActivate([ 
    app.SessionService, 
    function(session, instruction) { 
     console.log(session); 
     return true; 
    } 
])(app.ListsComponent); 

Edit: В качестве альтернативы, можно использовать событие routerOnActivate жизненного цикла на компоненте, а также использовать this.router.navigate отправить пользователь прочь, если они не должен будь там. Недостатком является то, что он разбивает историю браузера: если я перенаправляю вас асинхронно каждый раз, когда вы достигаете определенного URL-адреса, вы не можете использовать кнопку «Назад» в своем браузере очень полезно. Есть ли способ использовать router.navigatehistory.replaceState вместо history.pushState для такого рода ситуаций?

+0

DI должен быть возможен после выпуска [крючки для маршрутизатора впрыскиваются и соответствуют ядру] (https://github.com/angular/angular/issues/7485). В настоящее время вехой является кандидат на угловой 2. –

ответ

1

Я не знаю, если его лучший способ, но эти парни делают это за счет расширения и использования своих собственных <router-outlet> и переопределить метод CanActivate:

https://auth0.com/blog/2015/05/14/creating-your-first-real-world-angular-2-app-from-authentication-to-calling-an-api-and-everything-in-between/

Кроме того, вы можете использовать вместо routerOnActivate.

https://angular.io/docs/js/latest/api/router/OnActivate-interface.html Надеюсь, это поможет.

+1

Спасибо, я натолкнулся на это раньше, но я думаю, что с тех пор API маршрутизации сильно изменился; Я не мог заставить их работать. –

+0

Я вижу, почему бы вам не попробовать «routerOnActivate» вместо этого? Вы все же можете избежать того, чтобы компонент получал экземпляр, но у вас есть доступ к его введенным свойствам. https://angular.io/docs/js/latest/api/router/OnActivate-interface.html – Langley

2

Вы должны ввести его с помощью форсунки. Только быстрая копия паста из проекта я делаю:

@CanActivate((next: ComponentInstruction, prev: ComponentInstruction) => { 

    console.info('CanActivate hook! - can return boolean or Promise'); 

    var injector = Injector.resolveAndCreate([HTTP_PROVIDERS, YourService]); 
    var yourService = injector.get(YourService); 
    // do something with yourService 
    return new Promise(function(resolve, reject) { 
     resolve(true); 
    }); 

}) 

HTTP_PROVIDERS вы должны пройти вдоль, если ваш сервис, например инъекционной службу HTTP в конструкторе.

Я использую его, чтобы установить наблюдаемый параметр params следующего объекта. И следующий объект будет ваш следующий «Компонент/состояние»:

@CanActivate((next: ComponentInstruction, prev: ComponentInstruction) => { 

    console.info('properties component CanActivate hook! - can return boolean or Promise'); 
    var injector = Injector.resolveAndCreate([HTTP_PROVIDERS, PropertiesService]); 
    var propertiesService = injector.get(PropertiesService); 
    return new Promise(function(resolve, reject) { 
     next.params['properties'] = propertiesService.getProperties(); 
     resolve(true); 
    }); 

}) 

PropertiesService вызывает бэкенд и возвращает Observable, который представляет данные со свойствами

+0

Таким образом вы получаете новый экземпляр 'YourService', не так ли. Это может быть нежелательно. Обходной путь состоял в том, чтобы сохранить инжектор из вашего «AppComponent» с использованием статического поля, а затем использовать этот инжектор в '@CanActivate()' вместо создания нового. –

+0

Вы имеете в виду реализовать сервис как одноэлементный? –

+0

в моем случае Я думаю о том, действительно ли это имеет значение. Я не храню данные в службе. Это просто способ вызова бэкэнда. Как вы думаете? –

7

Большинство решений здесь будут представлять проблемы с загрузкой суб-зависимостей из другого места в иерархии, потому что они создают новый инжектор. Кроме того, это приводит к добавлению дополнительных (не общих) сервисов. Я рекомендую следующий шаблон, представленный Brandon в https://github.com/angular/angular/issues/4112

Он ссылается на этом шлепнуть: http://plnkr.co/edit/SF8gsYN1SvmUbkosHjqQ?p=preview

Его основная идея состоит в том одноэлементно инжектор, который он спасает, когда приложение инициализирует.Это обеспечивает доступ к корневым зависимостей вы уже настроили, и в дальнейшем позволяет ваши услуги для совместного использования в качестве одноэлементных, как они, вероятно, были предназначены:

import {Injector} from 'angular2/angular2'; 
let appInjectorRef: Injector; 

export const appInjector = (injector?: Injector):Injector => { 
    if (injector) { 
     appInjectorRef = injector; 
    } 

    return appInjectorRef; 
}; 

bootstrap([ServiceYouNeed]).then((appRef) => { 
    // store a reference to the injector 
    appInjector(appRef.injector); 
}); 
+0

Я пробовал это, но параметры маршрута не были разрешены. let routeParams: RouteParams = injector.get (RouteParams); –

1

Здесь (https://gist.github.com/clemcke/c5902028a1b0934b03d9) как протестировать решение addInjector(), что ссылки @shannon:

beforeEachProviders(()=>[PERSON_SERVICE_PROVIDERS]); 

beforeEach(inject([PersonService],()=>{ 
    let injector = Injector.resolveAndCreate([PERSON_SERVICE_PROVIDERS]); 
    appInjector(injector); 
})); 
0

Угловая 2,0 окончательное решение:

Поскольку мы определим отдельный класс, который реализует CanActivate, что класс может быть @Injectable, а другая зависимость может быть предоставлена ​​в его конструкторе в соответствии с ответом this.

Смежные вопросы