Как использовать сторонний модуль AngularJS (1.6) (angular-translate) в Angular (2 или 4)
Дело
Я нахожусь в процессе обновления приложения AngularJS (т. Е. Angular 1.6) до Angular (т. Е. Angular 4.1.3). Я решил сделать инкрементное обновление, поэтому в настоящее время AngularJS и Angular загружаются и работают. Пока все хорошо, но: один из сервисов AngularJS, который должен быть переписан на Angular, опирается на хорошо известный сервис $translate
который является частью стороннего модуля AngularJS (читайте Angular 1) pascalprecht.translate. Другими словами, $translate
сервис вводится в MyService
который должен стать сервисом Angular (читай Angular 4).
MyService
(раздетый) выглядит так:
import { Injectable } from '@angular/core';
@Injectable()
export class MyService {
// Here comes the injection (how to do it?).
constructor(private $translate: $translate) {
}
foo() {
// Use the service
this.$translate('HELLO_WORLD');
}
}
Он расположен в MyModule
:
import { NgModule } from '@angular/core';
import { MyService } from './my.service';
@NgModule({
providers: [
MyService
]
})
export class MyModule {
}
Эта проблема
Теперь, как я могу ввести $translate
в MyService
когда MyService
находится в угловом модуле, в то время как $translate
является частью стороннего модуля AngularJS?
Я знаю, как внедрить службу AngularJS в службу Angular, если служба AngularJS находится в том же модуле (или, по крайней мере, модуль является частью моего собственного решения). Это объясняется в официальных документах. Есть ли способ справиться со сторонним сервисом? Нужно ли регистрировать эту услугу в MyModule
провайдеры?
import { NgModule } from '@angular/core';
import { MyService } from './my.service';
// How this line should look line then?
import { $translate } from 'node_modules/angular-translate/...';
@NgModule({
providers: [
MyService,
$translate
]
})
export class MyModule {
}
Или я пытаюсь достичь невозможного?
1 ответ
Ну, после нескольких часов борьбы я наконец нашел решение. Вот:
Обновите сторонний сервис
Прежде всего, следуйте официальным инструкциям Angular и обновите поставщика услуг третьих лиц - $translate
, Как это:
AJS-модернизированные-providers.ts
import { InjectionToken } from '@angular/core';
import { downgradeInjectable } from '@angular/upgrade/static';
import 'angular-translate';
// Variable 'i' holds the standard AngularJS injector
export function $translateFactory(i: any) {
return i.get('$translate');
};
// There is no class representing the good old $translate service so we have
// a non-class dependency. Therefore we use an InjectionToken (Angular 4) or
// OpaqueToken (Angular 2).
export let $translate = new InjectionToken('$translate');
// Finally create the upgraded provider
export const $translateProvider = {
provide: $translate,
useFactory: $translateFactory,
deps: ['$injector']
};
Стоит отметить, что $translate
сервис может зависеть от других старых сервисов AngularJS, таких как (в моем случае) $translateStaticFilesLoader
или же $translateMessageFormatInterpolation
, Если это также ваш случай, обязательно расширьте приведенный выше код и сделайте обновленных провайдеров для этих сервисов (сохраните их в одном файле).
Убедитесь, что import
постановка работ
angular-translate
устанавливается как модуль узла, поэтому утверждение
import 'angular-translate';
работает просто отлично, если ваш tsconfig.json
настроен на использование moduleResolution: "node"
,
Тогда, конечно, вы должны убедиться, что import
Оператор будет работать даже после того, как код будет перенесен из TypeScript в ES5 (или какую бы цель вы не использовали) и был загружен загрузчиком модулей (в моем случае SystemJS).
Обратите внимание, что мы импортировали angular-translate
Сценарий, ничего не получая от него, только чтобы вызвать побочные эффекты. По сути, импорт гарантирует, что скрипт, содержащий желаемый сервис $translate
просто выполняется и записывается $translate
сервис для инжектора AngularJS $.
Зарегистрируйте модернизированного провайдера в модуле Angular
Теперь убедитесь, что новый обновленный поставщик $translate
услуга зарегистрирована среди других провайдеров MyModule
,
my.module.ts
import { NgModule } from '@angular/core';
import { MyService } from './my.service';
import { $translateProvider } from './ajs-upgraded-providers';
@NgModule({
providers: [
MyService,
$translateProvider
]
})
export class MyModule {
}
Используй это
Наконец, используйте $translate
служба в MyService
,
my.service.ts
import { Injectable, Inject } from '@angular/core';
import { $translate } from './ajs-upgraded-providers';
@Injectable()
export class MyService {
// Notice the usage of InjectionToken
constructor(@Inject($translate) private $translate: any) {
}
foo() {
this.$translate('hello.world').then((translation: string) => {
console.log(translation);
});
}
}