There are many of fascinating new features and enhancements in Angular 18. A notable improvement is the revamped Dependency Injection (DI) framework. Managing the dependencies of components and services is essential to creating scalable and maintainable applications using Angular's DI paradigm. To experience the new DI features in Angular 18, let's explore them in detail and work through an example.

What's New in the DI System of Angular 18?

  • Enhanced Tree-Shakability: Angular 18 makes sure that the final bundle contains only the code that is required. Smaller, more effective applications result from this.
  • Injection Contexts: With the introduction of new injection contexts, developers now have greater power and flexibility in defining and managing various dependency injection contexts.
  • Provider Scopes: Enhancing resource management and efficiency, this new feature gives you more precise control over the lifecycle of dependencies.
  • Simplified Provider Syntax: In Angular 18, a more understandable and maintainable syntax for declaring providers is introduced.

Using the New Dependency Injection Features in Angular 18 as an Example
Let's create a basic Angular 18 application to showcase these latest features in DI. We'll build a service, integrate it with a component, and investigate the recently added DI features.

First Step: Configuring the Angular 18 Project

First, use the Angular CLI to create a new Angular 18 project.

Step 1. Setting Up the Angular 18 Project
First, set up a new Angular 18 project using the Angular CLI
ng new angular18-di-demo
cd angular18-di-demo


Step 2. Creating a Service
We'll create a new service to provide some data to our component. Run the following command to generate the service:
ng generate service data

Open data.service.ts and implement the service like this:
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class DataService {
  private data = ['Angular 18', 'Dependency Injection', 'New Features'];

  constructor() {}

  getData(): string[] {
    return this.data;
  }
}

Here, the @Injectable decorator with providedIn: 'root' makes this service available throughout the application.

Step 3. Creating a Component
Next, we'll create a component to display the data provided by DataService. Run the following command.
ng generate component data-display

Open data-display.component.ts and inject DataService.
import { Component, OnInit } from '@angular/core';
import { DataService } from '../data.service';

@Component({
  selector: 'app-data-display',
  templateUrl: './data-display.component.html',
  styleUrls: ['./data-display.component.css']
})
export class DataDisplayComponent implements OnInit {
  data: string[] = [];

  constructor(private dataService: DataService) {}

  ngOnInit(): void {
    this.data = this.dataService.getData();
  }
}

In this component, we inject DataService in the constructor and use it to fetch data in the ngOnInit lifecycle hook.

Step 4. Displaying the Data

Open data-display.component.html and update the template to display the data:
<div>
  <h2>Data from DataService</h2>
  <ul>
    <li *ngFor="let item of data">{{ item }}</li>
  </ul>
</div>

Step 5. Using the Component
Include the DataDisplayComponent in your main application component. Open app.component.html and add the following.
<app-data-display></app-data-display>

Step 6. Running the Application
Run the application using the Angular CLI.

ng serve

Navigate to http://localhost:4200 in your browser. You should see the data displayed from DataService.

Summary

In this article, we've explored the new Dependency Injection features in Angular 18. By creating a simple service and component, we've seen how to use DI in Angular 18. The enhancements in the DI system, such as improved tree-shakability, injection contexts, provider scopes, and simplified syntax, make managing dependencies in Angular applications easier and more efficient. These features will help you maintain a clean and scalable codebase as you build more complex applications.