Skip to main content
Angular Fundamentals·Lesson 3 of 5

Services & Dependency Injection

Components should own only UI logic. Everything else — fetching data, business rules, shared state — belongs in a service. Angular's dependency injection (DI) system instantiates services for you and provides them wherever they're needed.

Creating a Service

ng generate service user
// src/app/user.service.ts
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'   // singleton across the whole app
})
export class UserService {
  private users = [
    { id: 1, name: 'Sabaoon', role: 'Developer' },
    { id: 2, name: 'Aisha',   role: 'Designer'  },
    { id: 3, name: 'Omar',    role: 'QA'         },
  ]

  getAll() {
    return this.users
  }

  getById(id: number) {
    return this.users.find(u => u.id === id)
  }
}

providedIn: 'root' means Angular creates one instance for the entire app and tree-shakes the service if nothing uses it.

Injecting into a Component

Add the service as a constructor parameter — Angular resolves it automatically:

import { Component, OnInit } from '@angular/core';
import { UserService } from '../user.service';

@Component({
  selector: 'app-user-list',
  templateUrl: './user-list.component.html'
})
export class UserListComponent implements OnInit {
  users: any[] = []

  constructor(private userService: UserService) {}

  ngOnInit() {
    this.users = this.userService.getAll()
  }
}

ngOnInit is the right lifecycle hook for fetching initial data — it runs after Angular sets all inputs.

HTTP Requests

Real services fetch data over HTTP. Angular ships HttpClient for this:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class PostService {
  private api = 'https://jsonplaceholder.typicode.com'

  constructor(private http: HttpClient) {}

  getPosts(): Observable<any[]> {
    return this.http.get<any[]>(`${this.api}/posts`)
  }
}

Subscribe in the component:

ngOnInit() {
  this.postService.getPosts().subscribe({
    next: posts  => this.posts = posts,
    error: err   => console.error(err),
  })
}

Remember to add HttpClientModule to your AppModule imports.

What a Service-Driven List Looks Like

Ctrl+Enter
HTML
CSS
JS
Preview

Lifecycle Hooks

HookWhen it runs
ngOnInitOnce, after first render — best for data fetching
ngOnChangesEvery time an @Input changes
ngOnDestroyJust before the component is removed — clean up subscriptions
ngAfterViewInitAfter the component's view and child views are initialised

Always unsubscribe from Observables in ngOnDestroy to prevent memory leaks, or use the async pipe which unsubscribes automatically.