Angular Series: Key Concepts in a Flash

Meriem TrabelsiMeriem Trabelsi
4 min read

1-Dependency Injection: General Perspective

Dependency Injection (DI) is a widely used programming technique in software development. It involves providing a class or object with its dependencies externally, rather than having the class create them internally. This approach makes a class independent of its dependencies and enhances code reusability. DI achieves these goals by decoupling the creation of an object from its usage, allowing dependencies to be replaced without altering the class that uses them.

In complex software development, adopting a modular design is recommended. This involves decomposing functionality into specific modules or classes with well-defined interfaces. Traditionally, modules create their own dependencies, leading to tightly coupled and less maintainable code. Dependency Injection (DI) addresses this by resolving dependencies at runtime instead of compile time. Rather than creating their own dependencies, objects rely on an external entity to provide and inject these dependencies.

💡
This helps you to follow SOLID’s dependency inversion and single responsibility principles.

The Single Responsibility Principle (SRP) states that each software module should have one and only one reason to change.

— Robert C. Martin

2-Dependency Injection in Angular

Angular implements the Dependency Injection (DI) principle to facilitate the development of modular and scalable applications. With DI, components, services, and other objects can be loosely coupled, making it easier to promote code reuse and test. Angular applications become more flexible and easier to refactor.

How it works in Angular

I find Angular's documentation very clear, and I recommend checking it out if you want to delve deeper. click-here

Two main roles exist in the DI system: dependency consumer and dependency provider. By adding the @Injectable decorator, a class becomes a provider and can be injected as a dependency

💫
In Angular, you can inject dependencies at the component level or the root module level.
@Injectable()
class FrstService {...}

After defining a dependency, the next step is to make it accessible within the Dependency Injection (DI) system. This can be achieved by providing the dependency, which can be done in multiple locations:

  • At the Component level, using the providers field of the @Component decorator. In this case the FirstService becomes available to all instances of this component. For example:
@Component({
  providers: [FirstService]
})
class FirstComponent {}

At the application level, using the providers field of the ApplicationConfig object passed to the bootstrapApplication function to provide a service or other Injectable . Here, the FirstService is available to all components, directives, and pipes declared in the NgModule. Registering a provider in the ApplicationConfig ensures that the same instance of a service is available to all relevant components, directives, and pipes.

Here, in app.module.ts:

Next:

const appConf: ApplicationConfig = {
    providers: [
      { provide: FirstService }
    ]
}

Then, in main.ts:

bootstrapApplication(AppComponent, appConf)
  • At the application level, you enable injection into other classes throughout the application. This is accomplished by adding the providedIn: 'root' field to the @Injectable decorator (which is the option by default when you generate a new service).
ng generate service Services/FirtService
import { Injectable } from '@angular/core';

@Injectable({
  // declares that this service should be created
  // by the root application injector.
  providedIn: 'root',
})
export class FirstService {
  // methods here ..
}

Injecting a dependency

The most common way to inject a dependency is by declaring it in a class constructor. When Angular instantiates a new instance of a component, directive, or pipe class, it identifies the required services or dependencies by examining the constructor parameter types. For example, if the FirstComponent requires the FirstService, the constructor might resemble this :

@Component({ … })
class FirstComponent {
  constructor(private service: FirstService) {}
}

Use cases and benefits

Dependency Injection is commonly used in Angular applications for various purposes. For example, services are often injected into components to encapsulate business logic and data retrieval operations. This separation of concerns allows components to focus on presentation logic while delegating data manipulation to services. Additionally, DI enables the use of PaaS provided by Angular, such as the HttpClient for making HTTP requests or the Router for navigation. The benefits of DI include improved code maintainability, testability, and scalability. By separating concerns and promoting code reuse, DI helps developers build robust apps.

👌
Overall, DI fosters a clean, modular architecture that leads to better software design and development practices.
Thanks for reading this! Exploring data binding in Angular and how components share data between them sounds like an engaging topic for the next blog post. Stay tuned !
3
Subscribe to my newsletter

Read articles from Meriem Trabelsi directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Meriem Trabelsi
Meriem Trabelsi

I am a curious, ambitious young woman passionate about the IT world 🙂. Acutually, I am software Engineering Student @ISI. More motivated to discover new technologies. I am interested in project management and the different approaches, business intelligence, web/mobile development, ISTQB (software testing) and so on ..