How to use the @Injectable decorator in Angular

The @Injectable decorator provided by the Angular framework allows classes to be decorated and registered with Angular’s dependency injection system. When a class is decorated with @Injectable, Angular creates and manages instances of that class, resolving its dependencies as needed.

When a class is marked with the @Injectable decorator, it becomes eligible for constructor injection. Constructor injection is a form of dependency injection where the dependencies of a class are provided through its constructor parameters. The framework analyzes the constructor parameters of the decorated class and resolves their dependencies automatically.

Key takeaways:

  • The @Injectable decorator allows services to be injected into components and other services.

  • @Injectable can register services at different levels: root, module, or component, providing flexibility in service scope.

  • Using providedIn: 'root' enables tree shaking, optimizing bundle size by excluding unused services.

  • @Injectable enables constructor injection, simplifying the process of injecting dependencies into classes.

  • The decorator generates metadata that Angular uses to resolve dependencies at runtime.

  • Angular’s hierarchical injector system allows for more granular control over service instances.

To use @Injectable, follow these steps:

Step 1: Create the service

First, we need to create a service class that we want to register. A service typically contains business logic, data retrieval, manipulation, or other functionality that can be shared across components. We can create a service using CLI by executing the following command:

ng generate service service-name
CLI to create a service

Step 2: Import injectable

Then we need to import the Injectable decorator from the @angular/core module.

//service-name.service.ts file
import { Injectable } from '@angular/core';

Step 3: Registering the service

We can then register the service at different levels.

Registering at the root level (default)

To register the service at root level, specify 'root' as the value for the providedIn property of @Injectable. Service becomes available throughout the application by registering at the root level.

//service-name.service.ts file
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class MyService {
constructor() {
console.log('MyService instance created!');
}
getMessage(): string {
return 'Hello, World!';
}
}

Now, we can use the service in any component of the application. Import the service in component-name.component.ts file and include it in the constructor of the component or service where we want to use it.

//component-name.component.ts file
import { Component } from '@angular/core';
import { MyService } from './my-service.service';
@Component({
selector: 'app-root',
template: `
<h1>{{ message }}</h1>
`
})
export class AppComponent {
message: string;
constructor(private myService: MyService) {
this.message = this.myService.getMessage();
}
}

The following is an example of an app displaying "Hello, World!" using a service by @Injectable registered at the root level.

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class MyService {
  constructor() {
    console.log('MyService instance created!');
  }

  getMessage(): string {
    return 'Hello, World!';
  }
}
App diplaying "Hello, World!" using a service by @Injectable (root)

Registering at a module level

To register a service at the module level, import the service in module-name.module.ts file and add the service in provider array of @NgModule of that module. Now, the service will be available only within that specific module and its child modules.

//module-name.module.ts file
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import {AppComponent} from './app.component';
import {MyModuleServiceService} from './my-module-service.service';
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, HttpClientModule],
providers: [MyModuleServiceService],
bootstrap: [AppComponent]
})
export class AppModule {}

We can now use the service in any component of that module. Import the service in component-name.component.ts file and include it in the constructor of the component where you want to use it.

//component-name.component.ts file
import { Component } from '@angular/core';
import {MyModuleServiceService} from './my-module-service.service';
@Component({
selector: 'app-root',
template: `
<h1>{{ message }}</h1>
`
})
export class AppComponent {
message: string;
constructor(private myService: MyModuleServiceService) {
this.message = this.myService.getMessage();
}
}

The following is an example of an app displaying "Hello, World!" using a service by @Injectable registered at the module level.

import { Injectable } from '@angular/core';

@Injectable()
export class MyModuleServiceService {

  constructor() {
    console.log('MyModuleService instance created!');
  }

  getMessage(): string {
    return 'Hello, World!';
  }
}
App diplaying "Hello, World!" using a service by @Injectable (module)

Registering at the component level

If you want each component to have its own instance of the service, import the service and provide the service directly in the component’s providers array.

//component-name.component.ts file
import { Component } from '@angular/core';
import { MyComponentService } from './my-component.service';
@Component({
selector: 'app-root',
template: `
<h1>{{ message }}</h1>
`,
providers: [MyComponentService]
})
export class AppComponent {
message: string;
constructor(private myService: MyComponentService) {
this.message = this.myService.getMessage();
}
}

The following is an example of an app displaying "Hello, World!" using a service by @Injectable registered at the component level.

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, HttpClientModule],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {}
App diplaying "Hello, World" using a service by @Injectable (component)

By following these steps and providing the necessary configuration, we can register a service using the @Injectable decorator in Angular. The service will be available for injection and use in your components, and other services based on the specified registration level.

Features of @Injectable

  • Dependency injection: By marking a class with @Injectable, Angular can analyze the class metadata and inject dependencies automatically, simplifying the management of dependencies.

  • Tree shaking: The providedIn property within @Injectable enables Angular's tree shaking optimization. This means that if a service is not used in the application, it won't be included in the final production bundle, reducing its size.

  • Hierarchical injector system: @Injectable supports a hierarchical injector system, allowing different levels of injectors for different parts of an application. This enables more granular control over the injection scope and can be beneficial in complex applications.

  • Testing and mocking: @Injectable makes it easier to write unit tests for Angular applications. It allows services to be easily mocked or replaced with stub implementations during testing, ensuring isolated and reliable testing scenarios.

Conclusion

The @Injectable decorator in Angular is a powerful feature that simplifies the management of dependencies and enables the use of dependency injection in classes. By using this decorator, classes can be registered with Angular's dependency injection system and have their dependencies resolved automatically. The @Injectable decorator offers flexibility in terms of registration levels, allowing services to be registered at the root level, module level, or component level based on the specific needs of the application.

Additionally, @Injectable provides benefits such as tree shaking optimization, hierarchical injection system, and easier testing and mocking. Overall, the @Injectable decorator is a valuable tool for building scalable and maintainable applications with Angular.

Frequently asked questions

Haven’t found what you were looking for? Contact Us


What is injectable in Angular service?

In Angular, @Injectable is a decorator that marks a class as available to be provided and injected as a dependency. When you apply @Injectable() to a service class, you’re telling Angular that this class is part of the dependency injection system.

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class MyService {
  // Service implementation
}

This decorator allows Angular to inject this service into components or other services that declare it as a dependency, enabling a modular and maintainable application structure.


What is the difference between @inject and injectable?

While both @Inject and @Injectable are related to dependency injection in Angular, they serve different purposes:

  • @Injectable: This decorator is used on the class that is being injected (usually a service). It tells Angular that this class can be used with the dependency injection system.
@Injectable({
  providedIn: 'root'
})
export class LoggingService {
  // Service implementation
}
  • @Inject: This decorator is used at the injection site (like a constructor parameter) to specify a custom provider or injection token for a dependency.
import { Inject } from '@angular/core';

constructor(@Inject('CONFIG') private config: AppConfig) { }

In essence, @Injectable is used on the providing class, while @Inject is used where the dependency is being injected.


What is the injectable() decorator used for?

The @Injectable() decorator in Angular serves several important purposes:

  • Dependency injection: It marks a class as available for dependency injection, allowing Angular to create and manage instances of the class.
  • Metadata generation: It generates metadata about the service, including its own dependencies, which Angular uses to resolve and inject dependencies.
  • Tree shaking: When used with providedIn: 'root', it enables tree shaking, allowing unused services to be excluded from the final bundle.
  • Scope definition: It can define the scope of the service (root, module, or component level) using the providedIn property.

What is the role of injector in Angular?

The injector in Angular plays a crucial role in the dependency injection system:

  • Dependency resolution: It’s responsible for creating instances of services and resolving their dependencies.
  • Instance management: The injector maintains a container of service instances, ensuring that singleton services are only created once.
  • Hierarchical injection: Angular uses a hierarchical injection system, where injectors are organized in a tree structure mirroring the component tree.
  • Lazy loading: Injectors support lazy loading of modules, creating child injectors for lazy-loaded modules.
  • Custom providers: They allow the use of custom providers, enabling more complex dependency injection scenarios.

Free Resources

Copyright ©2024 Educative, Inc. All rights reserved