Services & Dependency Injection
Share logic across components using injectable services and Angular's built-in dependency injection system.
Why Services Exist
A service is a plain TypeScript class dedicated to logic that doesn't belong to any one component — fetching data, managing shared state, or wrapping a browser API. Components stay focused on presenting UI; services hold the reusable logic behind it.
Creating a Service
The Angular CLI generates a service exactly like a component, and the @Injectable decorator marks the class as something Angular's dependency injection system can provide.
ng generate service posts# shorthand: ng g s posts// posts.service.tsimport { Injectable } from '@angular/core';
@Injectable({ providedIn: 'root' })export class PostsService { private posts = [{ id: 1, title: 'Hello Angular' }];
getPosts() { return this.posts; }}This tells Angular to create exactly one shared instance of the service for the whole application (a singleton), and to make it available anywhere without needing to list it in a providers array manually.
Injecting a Service via the Constructor
The classic way to receive a service is a typed constructor parameter — Angular's DI system automatically supplies the right instance.
import { Component } from '@angular/core';import { PostsService } from './posts.service';
@Component({ selector: 'app-posts', standalone: true, template: `...` })export class PostsComponent { posts;
constructor(private postsService: PostsService) { this.posts = this.postsService.getPosts(); }}The Modern inject() Function
Modern Angular offers inject() as an alternative, letting you retrieve a dependency as a plain function call — useful outside a constructor (like inside a field initializer or a route guard function).
import { Component, inject } from '@angular/core';import { PostsService } from './posts.service';
@Component({ selector: 'app-posts', standalone: true, template: `...` })export class PostsComponent { private postsService = inject(PostsService); posts = this.postsService.getPosts();}How Dependency Injection Works
Rather than a component creating its own instance of a service directly (new PostsService()), it declares that it needs one, and Angular's injector supplies it — resolving the exact right instance based on where the service is provided (root, a specific component, or a route). This makes services easy to swap out, mock in tests, and share consistently across the app.
Common Beginner Mistakes
This bypasses Angular's DI entirely, creating a separate instance that won't share state with the rest of the app, and can't be mocked in tests the standard way — always inject services, never construct them manually.
Without it, Angular has no metadata to know how to construct or provide the class — this decorator is required even for a service with no dependencies of its own.
FAQs
Not entirely — both remain fully supported; inject() is often preferred in modern code for its flexibility outside constructors, but constructor injection is still common and equally valid.
Yes — services can depend on other services exactly like components do, and Angular resolves the whole dependency graph automatically.
Summary
Services hold reusable logic outside components, and Angular's dependency injection system supplies the right instance automatically, whether via a constructor or inject(). Next, you'll go deeper into how providers and injection tokens control that resolution.