Two instances of ToastyService when lazy loading routes and shared module
tomasisby opened this issue · comments
- I'm submitting a ...
[x] bug report
[ ] feature request
[ ] question about the decisions made in the repository - Do you want to request a feature or report a bug?
bug - What is the current behavior?
When I create lazy loaded routes with a shared module, two instances of ToastyService is created and no toasts is shown. Only ToastService in lazy loaded module gets updated. - If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem via https://plnkr.co or similar.
Tried to do a Plunker but didn't find out how to include Toasty in this. Here is the code that differs from Angular Quickstart:
app.module
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { SharedModule } from './shared.module';
import { routing } from './app.routing';
@NgModule({
imports: [
BrowserModule,
SharedModule,
routing
],
declarations: [
AppComponent
],
bootstrap: [AppComponent]
})
export class AppModule { }
app.component
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: `<h1>My First Angular App</h1>
<router-outlet></router-outlet>
<ng2-toasty position="top-right"></ng2-toasty>`
})
export class AppComponent {
}
app.routing
import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { StartComponent } from './start.component';
const appRoutes: Routes = [
{ path: '', redirectTo: 'start', pathMatch: 'full' },
{ path: 'start', loadChildren: 'app/start.module#StartModule' }
];
export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes);
shared.module
import { NgModule, ModuleWithProviders } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { ToastyModule, ToastyService } from 'ng2-toasty';
@NgModule({
imports: [
CommonModule,
ToastyModule.forRoot()
],
declarations: [],
exports: [
CommonModule,
FormsModule,
ToastyModule
]
})
export class SharedModule {
}
start.module
import { NgModule } from '@angular/core';
import { StartComponent } from './start.component';
import { SharedModule } from './shared.module';
import { routing } from './start.routing';
@NgModule({
imports: [
SharedModule,
routing
],
declarations: [
StartComponent
],
exports: []
})
export class StartModule { }
start.component
import { Component } from '@angular/core';
import {ToastyService, ToastyConfig, ToastOptions, ToastData} from 'ng2-toasty';
@Component({
moduleId: module.id,
selector: 'my-start',
template: `<button (click)="addToast()">Add Toast</button>`
})
export class StartComponent {
constructor(private toastyService:ToastyService, private toastyConfig: ToastyConfig) {
// Assign the selected theme name to the `theme` property of the instance of ToastyConfig.
// Possible values: default, bootstrap, material
this.toastyConfig.theme = 'material';
}
addToast() {
// Just add default Toast with title only
this.toastyService.default('Hi there');
// Or create the instance of ToastOptions
var toastOptions:ToastOptions = {
title: "My title",
msg: "The message",
showClose: true,
timeout: 5000,
theme: 'default',
onAdd: (toast:ToastData) => {
console.log('Toast ' + toast.id + ' has been added!');
},
onRemove: function(toast:ToastData) {
console.log('Toast ' + toast.id + ' has been removed!');
}
};
// Add see all possible types in one shot
this.toastyService.info(toastOptions);
this.toastyService.success(toastOptions);
this.toastyService.wait(toastOptions);
this.toastyService.error(toastOptions);
this.toastyService.warning(toastOptions);
}
}
start.routing
import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { StartComponent } from './start.component';
const appRoutes: Routes = [
{ path: '', component: StartComponent }
];
export const routing: ModuleWithProviders = RouterModule.forChild(appRoutes);
- What is the expected behavior?
When using lazy loaded routes and shared module, ToasyService should still be a singleton. - Please tell us about your environment:
- Angular version: 2.0.0
- Browser: [all ]
Hi @tomasisby
I didn't test it in lazy loading environment. Thanks for prompt.
Hello!
I've meddled around with Angular core.module and found a way to make this work. You need to export the ToastyModule in shared.module and ToastyService in core.module, like this:
In shared.module:
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { ToastyModule } from 'ng2-toasty';
@NgModule({
imports: [
CommonModule,
ToastyModule
],
declarations: [],
exports: [
CommonModule,
FormsModule,
ToastyModule
]
})
export class SharedModule {}
And in core.module you take care of the services:
import { NgModule, Optional, SkipSelf } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ToastyService, ToastyConfig } from 'ng2-toasty';
@NgModule({
imports: [
CommonModule
],
declarations: [],
exports: [],
providers: [
ToastyService,
ToastyConfig,
]
})
export class CoreModule {
constructor( @optional() @SkipSelf() parentModule: CoreModule) {
if (parentModule) {
throw new Error('CoreModule is already loaded. Import it in the AppModule only');
}
}
}
And then in app.module you import both shared.module and core.module so you can get a singleton service for the root application:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { SharedModule } from './shared.module';
import { CoreModule } from './core/core.module';
import { routing } from './app.routing';
@NgModule({
imports: [
BrowserModule,
SharedModule,
CoreModule,
routing
],
declarations: [
AppComponent
],
bootstrap: [AppComponent]
})
export class AppModule { }
And voila! It works as expected with only one instance of toasty service for lazy loaded routes as well.
Impressive.
Thanks for time and sharing code.
Sorry to write on a closed issue, but is there any way to make this work without the core module pattern? Right now it's spawning a new service for each module.