Module With Providers - deependhamecha/angular GitHub Wiki

Dont know the exact purpose of ModuleWithProviders interface but majorly people use it to make a singleton service instance across eager modules and lazy loaded modules.

Suppose, there is

shared/shared.module.ts

@NgModule({
  providers: [CounterService]
})
export class SharedModule { }

shared/counter.service.ts

@Injectable()
export class CounterService {
  counter = 0;
}

app.module.ts

@NgModule({
  imports: [BrowserModule, SharedModule, routing],
  declarations: [AppComponent, EagerComponent],
  bootstrap: [AppComponent],
})
export class AppModule {}

Now, suppose there is a lazy loaded module.

lazy.module.ts

const routes: Routes = [
  { path: '', component: LazyComponent }
];

export const routing: ModuleWithProviders = RouterModule.forChild(routes); // You dont need to re-export it

@NgModule({
  imports: [routing],
  declarations: [LazyComponent],
})
export class LazyModule {}


/* OR ELSE
Doesn't make a difference though, either you do NgModule export or JS module export.
@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule],
  declarations: [LazyComponent],
})
export class LazyModule {}
*/

Now,

lazy.component.ts

@Component({
  selector: 'app-lazy',
  template: `
    <p>Lazy Component</p>
    <button (click)="increaseCounter()">Increase Counter</button>
    <p>Counter: {{ counterService.counter }}</p>
  `
})
export class LazyComponent  {
  
  constructor(public counterService: CounterService) {}

  increaseCounter() {
    this.counterService.counter += 1;
  }
}

This will create 2 separate instance when trying to access from a different lazy loaded module or eagerly loaded module.

To make it singleton, use following.

shared.module.ts

@NgModule({})
export class SharedModule {
  static forRoot(): ModuleWithProviders {
    return {
      ngModule: SharedModule,
      providers: [CounterService],
    };
  }
}

app.module.ts

@NgModule({
  imports: [BrowserModule, SharedModule.forRoot(), routing],
  declarations: [AppComponent, EagerComponent],
  bootstrap: [AppComponent],
})
export class AppModule {}

lazy.module.ts

@NgModule({
  imports: [routing],
  declarations: [LazyComponent],
})
export class LazyModule {}

Now, when you use it from any Lazy Loaded Module. It will use same instance created in SharedModule.

⚠️ **GitHub.com Fallback** ⚠️