Как использовать сторонний модуль 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);
        });
    }
}
Другие вопросы по тегам