Angular 3: Services and Dependency Injection
/ 2 min read
Table of Contents
Page components should focus on the interface. Shared data and business operations belong in a service.
What is dependency injection?
Dependency injection means a class asks Angular for something it needs instead of constructing it itself.
private readonly topicService = inject(Topic);Angular creates and supplies the service. With providedIn: 'root', the application shares one instance.
1. Generate the service
ng generate service services/topicimport { Injectable, signal } from '@angular/core';
export interface TopicItem { id: number; name: string; completed: boolean;}
@Injectable({ providedIn: 'root' })export class Topic { readonly topics = signal<TopicItem[]>([ { id: 1, name: 'Components', completed: true }, { id: 2, name: 'Signals', completed: true }, { id: 3, name: 'Routing', completed: false } ]);
findById(id: number): TopicItem | undefined { return this.topics().find(topic => topic.id === id); }}2. Use it from a page
private readonly topicService = inject(Topic);
protected readonly topic = computed(() => this.topicService.findById(this.topicId()));computed() derives a value from signals. When the route ID or topic list changes, Angular recalculates the selected topic.
3. Add an update operation
toggleCompleted(id: number): void { this.topics.update(topics => topics.map(topic => topic.id === id ? { ...topic, completed: !topic.completed } : topic ) );}We create a new object and array instead of mutating the existing topic. This keeps state changes predictable.
Will the detail page and dashboard get separate services?
No. A root-provided service is shared, so both pages observe the same state.
Checkpoint
Change a topic on its detail page, return to the dashboard, and confirm the dashboard shows the updated status.
Small challenge
Add setCompleted(id, completed) and make it do nothing when the requested status is already set.
Navigation: Previous: Routing · Series overview · Next: Signal state