Мне нужно внедрить службу во внешнюю библиотеку, чтобы использовать ее в директиве. эта директива будет использоваться в разных приложениях и в разных модулях каждого приложения. Каждый модуль будет внедрять свой собственный сервис.
Я создаю токен ввода и интерфейс службы в модуле библиотеки и импортирую их в модули, которые будут использоваться в основном приложении.
затем я предоставляю услугу, используя useExisting с этим токеном, и в директиве использую @Inject(INJECTION_TOKEN) в конструкторе.
но у меня всегда есть этот результат, когда я загружаю компонент, где используется директива: «NullInjectorError: R3InjectorError (DashboardModule) [токен службы InjectionToken -> токен службы InjectionToken»
В моем библиотечном модуле
import { Directive } from './directives/directive.directive';
@NgModule({
exports: [
...,
Directive
],
imports: [CommonModule,...],
declarations: [
...,
Directive
]
})
export class LibraryModule {
}
export const SERVICE_ADAPTER: InjectionToken<ServiceAdapter> =
new InjectionToken('service token');
export interface ServiceAdapter {
a(): void
}
В моей директиве библиотеки:
import { Directive, ElementRef, EventEmitter, HostListener, Inject, Input, Output } from '@angular/core';
import { ServiceAdapter, SERVICE_ADAPTER } from '../library.module';
@Directive({
selector: '[myDirective]'
})
export class Directive {
@Input() field: string = ''
@Input() method: string = ''
constructor(private el: ElementRef, @Inject(SERVICE_ADAPTER) protected service: ServiceAdapter) {}
@HostListener('keyup', ['$event'])
keyup(event: any) {
...
}
}
В модуле, где я собираюсь его использовать:
...
import { LibraryModule,SERVICE_ADAPTER } from 'Library...';
@NgModule({providers: [
{ provide: SERVICE_ADAPTER, useExisting: ProjectsService }
],
declarations: [
...
],
imports: [
LibraryModule,
]
})
export class ProjectsModule {
}
да, служба уже создана в родительском компоненте. Кстати, проблема сохраняется при использовании useClass
Похоже, что сообщение об ошибке, которое вы получаете, указывает на отсутствие существующего экземпляра предоставленной службы, что вызывает NullInjectorError. 1) Используйте useClass вместо useExisting и импортируйте класс обслуживания в модуль, где вы пытаетесь его использовать. 2) Предоставьте услугу в родительском модуле или компоненте, чтобы ее можно было повторно использовать в модуле LibraryModule и модуле, в котором вы пытаетесь ее использовать.
я понял, если я введу его в конструктор LibraryModule, он введет нормально, но я не знаю, как использовать его в директиве
Я думаю, что понимаю вашу проблему: вам нужны директивы в пакете npm, потому что вы хотите использовать его в разных приложениях. Вы хотите реализовать абстрактную службу, которая может взаимодействовать с вашей директивой. Мне нет смысла реализовывать сервис для каждого использования в вашей библиотеке. Вот почему вы хотите работать с инъекционным токеном. Таким образом, вы можете внедрить индивидуальную реализацию абстрактного сервиса для каждого сценария. Я прав? Итак, ваше решение «forRoot». Искала для вас ссылку: medium.com/slackernoon/…
@DanielMichelfelder не совсем так. да, библиотека будет в npm, но в основном приложении эта директива будет использоваться во многих загруженных lazo модулях. В каждом модуле с ленивой загрузкой эта директива должна использовать разные службы. Вот почему я использую инъекционный токен, созданный в библиотеке.





Когда я правильно вас понимаю, приведенная выше ссылка является решением для вас. Если вы хотите, чтобы для каждого модуля с ленивой загрузкой ваш собственный/индивидуальный экземпляр service_adapter "forRoot - Concept" был вашим решением.
Вам нужен модуль для вашей директивы в библиотеке, например:
export interface IDirectiveModuleConfig {
serviceAdapterConfiguration?: Provider;
}
@NgModule()
export class YourDirectiveModule{
public static forRoot(config: IDirectiveModuleConfig = {}): ModuleWithProviders<YourDirectiveModule> {
return {
ngModule: YourDirectiveModule,
providers: [
config.serviceAdapterConfiguration
]
};
}
}
В вашем лениво загруженном модуле вы можете указать, как будет предоставляться ваша услуга
@NgModule(
{
imports: [
YourDirectiveModule.forRoot({
provide: ServiceAdapter,
useClass: CustomImplementationServiceAdapter
})
]
}
)
export class LazyLoadedModule {
}
Спасибо! Мне пришлось изменить значение предоставления, потому что с ServiceAdapter оно не работало, но если я предоставляю строку или с помощью InjectionToken, импортированного из модуля директивы, все работает нормально. Наконец-то я использовал инъекциюToken. Сделал стекблиц с работающим ЗДЕСЬ
Пожалуйста. Я рад видеть, что это работает хорошо. 😜
При использовании useExisting необходимо убедиться, что служба, которую вы пытаетесь использовать, уже создана и предоставлена в родительском модуле или компоненте. Параметр useExisting, по сути, указывает Angular использовать существующий экземпляр службы, а не создавать новый.