Angular 2 Как сделать сервис singleton доступным для ленивых загружаемых модулей

115
14

В соответствии с моим пониманием Angular 2 rc5, чтобы сделать сервис из другого модуля (не AppModule), доступного в качестве одноэлементного для каждого компонента, даже те, которые были загружены ленивым, мы не включаем в службу providers массив этого другого модуля. Вместо этого экспортируем его с помощью RouterModule.forRoot() и импортируем результат в AppModule


В соответствии с документами:


SharedModule должен предоставлять только UserService при импорте корневой AppModule. Метод SharedModule.forRoot помогает нам справиться с этим вызов... SharedModule не имеет providers... Когда мы добавляем SharedModule для импорта AppModule, мы вызываем forRoot. В при этом AppModule получает экспортированные классы и SharedModule предоставляет однопользовательский UserService провайдер при том же время



Я действительно борется с тем, как сделать стороннюю услугу (услугу, используемую модулем в массиве imports моего AppModule), доступную для ленивых загруженных маршрутов. У меня нет контроля над этим сторонним модулем, поэтому я не могу просто удалить эту службу из массива NgModule.providers этого модуля и поместить его внутри RouterModule.forRoot(), как и с одной из моих служб.


Конкретная услуга MdIconRegistry, которая находится в providers для MdIconModule of Angular Material 2 alpha 7-3. Эта служба используется для регистрации значков svg, которые затем могут отображаться на странице с тегом <md-icon svgIcon='iconName'>. Итак:


    Я импортировал MdIconModule в свой корень AppModule
    Я использовал эту услугу для регистрации значков svg в AppComponent

Значок отображается и работает хорошо, но только в модулях, которые были загружены при запуске. Lazy-загруженные модули не могут видеть эти значки, поэтому я подозреваю, что инжектор Angular не вводит тот же экземпляр службы MdIconRegistry.


tl; dr: Как мне сделать сервис от стороннего модуля доступным для моих ленивых компонентов?

Вот плункер, демонстрирующий проблему (закодирован в typescript).


PS: Это только привлекло внимание разработчика MdIconModule в github.

спросил(а) 2021-01-19T16:04:13+03:00 2 месяца, 3 недели назад
1
Решение
131

I do not think it has anything to do with the component being lazy-loaded.

LazyLoadedComponent не является частью AppModule - он является частью LazyModule. Согласно документам, компонент может быть только частью одного модуля. Если вы также попробуете добавить LazyLoadedComponent в AppModule, вы получите сообщение об ошибке. Таким образом, LazyLoadedComponent даже не видит MdIconModule. Вы можете подтвердить это, посмотрев на вывод шаблона в отладчике - он не изменился.


<md-icon svgIcon="play"></md-icon>

Решение похоже на добавление MdIconModule к LazyModule, и хотя это само по себе не устраняет проблему, оно добавляет ошибку в вывод.


Значок получения ошибки: Ошибка: невозможно найти значок с именем ": play"



И теперь вывод шаблона выглядит так, поэтому мы знаем, что он загружается.


<md-icon role="img" svgicon="play" ng-reflect-svg-icon="play" aria-label="play"></md-icon>

Я добавил вызов addSvgIconSet из LazyLoadedComponent и получил его работу... поэтому это доказывает наличие экземпляра службы MdIconRegistry для каждого компонента - не то, что вы хотите, но можете указать вам в правильном направлении.

Вот новый сюжет - http://plnkr.co/edit/YDyJYu?p=preview


После дальнейшего обзора я нашел это в docs:


Почему служба, предоставляемая в ленивом загруженном модуле, видима только для этого модуля?

В отличие от поставщиков модулей, загружаемых при запуске, поставщики ленивых загружаемых модулей модулируются по модулю.



Окончательное обновление! Вот ответ. MdIconModule неправильно настроен для ленивых загружаемых компонентов... но мы можем легко создать собственный модуль, который правильно настроен и использует его.


import { NgModule } from '@angular/core';
import { HttpModule } from '@angular/http';

import { MdIcon } from '@angular2-material/icon';
import { MdIconRegistry } from '@angular2-material/icon';

@NgModule({
imports: [HttpModule],
exports: [MdIcon],
declarations: [MdIcon]
})
export class MdIconModuleWithProviders {
static forRoot(): ModuleWithProviders {
return {
ngModule: MdIconModuleWithProviders,
providers: [ MdIconRegistry ]
};
}
}


Plunk обновляется и полностью работает. (извините, обновлено то же самое) → http://plnkr.co/edit/YDyJYu?p=preview


Можно отправить запрос на перенос таким образом, чтобы Angular Материал экспортировал модули обоих стилей.

ответил(а) 2021-01-19T16:04:13+03:00 2 месяца, 3 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема