Skip to content

Creating and Injecting a Service

You know what services are and why they exist. Now let’s create one and use it.

Use the CLI to generate a service:

Terminal window
ng generate service services/movie

Short form:

Terminal window
ng g s services/movie

This creates two files:

src/app/services/
├── movie.service.ts ← the service class
└── movie.service.spec.ts ← the unit test

The generated movie.service.ts:

import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class MovieService {}

The classic way to inject a service is via the constructor:

import { Component, OnInit } from '@angular/core';
import { MovieService } from '../../services/movie.service';
import { Movie } from '../../models/movie.model';
@Component({
selector: 'app-home',
standalone: true,
templateUrl: './home.html',
styleUrl: './home.css'
})
export class Home implements OnInit {
movies: Movie[] = [];
constructor(private movieService: MovieService) {}
ngOnInit(): void {
this.movieService.getPopular().subscribe(movies => {
this.movies = movies;
});
}
}

Angular sees MovieService in the constructor parameter list and injects the singleton instance before ngOnInit runs.

The inject() function — modern alternative

Section titled “The inject() function — modern alternative”

Angular 14+ provides a functional alternative to constructor injection: inject(). It retrieves a service from the DI system without requiring a constructor parameter:

import { Component, OnInit, inject } from '@angular/core';
import { MovieService } from '../../services/movie.service';
@Component({ /* ... */ })
export class Home implements OnInit {
private movieService = inject(MovieService);
movies: Movie[] = [];
ngOnInit(): void {
this.movieService.getPopular().subscribe(movies => {
this.movies = movies;
});
}
}

inject() must be called during class field initialization or inside a function that runs in an injection context (like ngOnInit of a component, or the body of a guard function). It cannot be called asynchronously.

Both constructor injection and inject() are valid. In CinemaVault:

  • Components use inject() — it avoids constructor boilerplate when a class only injects services
  • Guards use inject() — guards are plain functions, so there is no constructor option

Choose whichever reads more clearly in context. Either way, Angular’s DI system supplies the same singleton instance.

Here is a MovieService with a getPopular() method, and a Home component that uses it:

movie.service.ts
import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, map } from 'rxjs';
@Injectable({ providedIn: 'root' })
export class MovieService {
private http = inject(HttpClient);
private readonly base = 'https://api.themoviedb.org/3';
getPopular(): Observable<Movie[]> {
return this.http.get<MoviesResponse>(`${this.base}/movie/popular`, {
params: { api_key: API_KEY }
}).pipe(map(res => res.results));
}
}
home.ts
@Component({ /* ... */ })
export class Home implements OnInit {
private movieService = inject(MovieService);
movies: Movie[] = [];
loading = true;
ngOnInit(): void {
this.movieService.getPopular().subscribe({
next: movies => {
this.movies = movies;
this.loading = false;
},
error: () => {
this.loading = false;
}
});
}
}
  1. Generate ng g s services/greeting.
  2. Add a getGreeting(name: string): string { return 'Hello, ' + name + '!'; } method.
  3. Inject GreetingService into AppComponent using inject().
  4. Display the result in the template: {{ greeting }} where greeting = this.greetingService.getGreeting('Angular').
  5. Try both inject() and constructor injection and confirm both produce the same result.
  • Generate services with ng generate service services/name.
  • Constructor injection: constructor(private myService: MyService) {} — Angular injects the singleton automatically.
  • inject() function: private myService = inject(MyService) — a modern alternative without constructor boilerplate.
  • Services injected with inject() must be called during class initialization or within an injection context.
  • Both approaches provide the same singleton instance from Angular’s DI system.