Как я могу инициализировать сторонний модуль в моем.forRoot() в угловых

Я строю внутреннюю библиотеку для наших проектов, используя Angular 6+. Я использую .forRoot() подход к регистрации глобальных услуг, как это задокументировано.

Моя библиотека будет использовать ngx-toastr предоставлять уведомления. Поскольку я не хочу, чтобы каждый проект имел дело со всеми вариантами ngx-toastr Я абстрагирую большую часть этого за notifications оказание услуг.

Путь ngx-toastr работает, вы можете установить глобальные параметры, передавая эти глобальные параметры ToastrModule.forRoot(),

как я могу настроить ToastrModule как часть моей forRoot() ?

Это явно плохая идея добавить любой код внутри .forRoot(), но это правильный способ инициализировать его прямо в моем @NgModule()? как это:

@NgModule({
    imports: [ToastrModule.forRoot(/* options go here? */)],
    declarations: [],
    exports: []
})
export class ToolsCoreModule {
    static forRoot(): ModuleWithProviders {
        return {
            ngModule: ToolsCoreModule,
            providers: [],
        };
    }
}

Как это будет взаимодействовать, если кто-то из команды решит также позвонить? ToastrModule.forRoot() в рамках собственной инициализации модуля?

2 ответа

Как упоминалось в @migh, должен вызываться только, но вложенный в forRoot() провайдер по-прежнему вызывается AppModuleне так ли?

Итак, вы можете сделать следующее

      @NgModule({
    imports: [],
    declarations: [],
    exports: [ToastrModule]
})
export class ToolsCoreModule {
    static forRoot(/* your options */): ModuleWithProviders {
        return {
            ngModule: ToolsCoreModule,
            providers: [...ToastrModule.forRoot(/* toastr options */).providers],
        };
    }
}

Как это будет взаимодействовать, если кто-то в команде решит также позвонить ToastrModule.forRoot() в рамках собственной инициализации модуля?

Вы можете получить ошибку во время выполнения или странное поведение.

Чтобы избежать «странного поведения», вам также следует добавить в свой модуль этот шаблон, предотвращающий двойную регистрацию:

      constructor(@Optional() @SkipSelf() parentModule?: ToolsCoreModule)
{
    if (parentModule)
    {
        throw new Error(
            "ToolsCoreModule is already loaded. Import it in the AppModule only!");
    }
}

Этот шаблон взят из официальной документации:https://angular.io/guide/singleton-services#prevent-reimport-of-the-greetingmodule

Корневой модуль, который экспортирует ваш сервис уведомлений через providers должен быть единственным, который использует ToastrModule.forRoot() в imports декларация.

forRoot() Вызов - это соглашение, а не что-то, что поддерживается платформой. Другие не должны вызывать это при определении своих NgModules, если он уже был вызван выше.

Как упомянуто в угловой документации:

Только позвонить и импортировать .forRoot() результат в модуле корневого приложения, AppModule, Импортирование его в любой другой модуль, особенно в модуль с отложенной загрузкой, противоречит цели и может привести к ошибке времени выполнения.

...

forRoot() а также forChild() являются условными именами методов, которые настраивают службы в корневых и функциональных модулях соответственно.

Если ваша глобальная конфигурация для ToastrModule никогда не меняется, я не думаю, что есть что-то плохое в том, как вы задали вопрос в своем фрагменте.

Однако, если конфигурация может измениться в зависимости от потребителей ToolsCoreModuleты не должен звонить forRoot() для каждой отдельной конфигурации, поскольку это неправильно по соглашению. В этом случае вы можете рассмотреть возможность создания оберток вокруг третьего аргумента вызовов toast для передачи общей конфигурации (например, this.toastrService.error(msg, title, config)).

Другие вопросы по тегам