Are your Angular Services Singleton ?
Tags: angular, services, learning
Published: 2021-10-09 07:16:36

Angular has the concept of services which allows to share the data between components.

In this blog we will learn about service instances creation in Angular.

What happens when we inject service in root of a lazy module, is the same instance used for multiple lazy modules.

What if we want to have a separate instance per module and per component ?

> We will use the same code example as used in common chunks [example](https://dev.to/sanketmaru/common-chunks-in-angular-3eel). If you haven't gone through that blog do checkout to learn on why common chunks are created.

Let's begin then.

### Common Service Instance

Let's start where we ended in the previous [post](https://dev.to/sanketmaru/common-chunks-in-angular-3eel). We have two lazy modules user and account and currently share the same toast module which is built in a separate chunk.

As we have given as `@Injectable({ providedIn: "root" })` for the toast service, a singleton instance of service is created and is shared among all the lazy modules.

As toast module is shared, we will have a common count of messages for both the modules.

Lets see it in action below -

{% vimeo 627154461 %}

### Service Instance per Component

We can see the count of toast message is common and also toast module is included in the common chunk.

However, now we want to keep a count of how many times user clicks the button in a particular module. Individual count for user module and account module.

We will tweak the code in individual components and see how it behaves.

```javascript
@Component({
  selector: 'app-account',
  templateUrl: './account.component.html',
  styleUrls: ['./account.component.scss'],
  providers: [ToastService]
})
export class AccountComponent {
  ...code
}

@Component({
  selector: 'app-user',
  templateUrl: './user.component.html',
  styleUrls: ['./user.component.scss'],
  providers: [ToastService]
})
export class UserComponent {
  ...
}
```
Above code with create two instances of ToastService which will be respective to user component and account component.


{% vimeo 627179471 %}

### Service Instance per Module

Great, we have multiple instance of service created and also toast module code is in common chunk. 

As its seen, the count is always reset to 0. This is because the service instance is getting destroyed as soon as component is destroyed. When user navigates to a new route, earlier component is destroyed and new is created.

As we are creating instance at component level, we get a new instance every time. This might be useful if we want to reset the count.

To solve this we will create the instance at module level, so it will have a single instance for a particular module and also code will be served from common chunk.

To do this add ToastService in providers section of module which can be done from code as below -

```javascript
@NgModule({
  declarations: [
    UserComponent
  ],
  imports: [
    CommonModule,
    UserRoutingModule,
    ToastModule
  ],
  providers: [ToastService],
  exports: [ToastModule]
})
export class UserModule { }

@NgModule({
  declarations: [
    AccountComponent
  ],
  imports: [
    CommonModule,
    AccountRoutingModule,
    ToastModule
  ],
  providers: [ToastService],
  exports: [ToastModule]
})
export class AccountModule { }
```

Let's see now in action how the behaviour is.

{% vimeo 627185550 %}

Great, now we have service instance per module and it stores the count for a particular lazy module.

### Service Injection at App Root

Coming to the last case if we include toast service to the main app module.

This can be done by importing in providers section of app module.

```javascript
@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    ToastModule
  ],
  providers: [ToastService],
  bootstrap: [AppComponent]
})
export class AppModule { }
```
Lets see the demo.

{% vimeo 627195603 %}

With this, now we have 3 instances of toast service. 
1. For App Module
2. User ( Lazy ) Module
3. Account ( Lazy ) Module

Even if don't have the providers section in main app module, it will still have three separate instance for app and respective lazy modules as in service injectable we have providedIn as `root`.

For all modules present in app module, it would use instance of the app module one and instances of lazy modules would be separate.

This is because Angular creates separate injector tree for lazy module.

So, with this post we have learned scenarios in which a common service instance can be used per module or a component or by have it at root level. 

Complete code can be found at my GitHub branch [service_creation](https://github.com/sanketmaru/angular-service-instance/tree/service_creation).

Thanks for checking this blog and let me know if you find it useful.