Skip to main content
Practice Problems

Services and dependency injection in Angular

What are Services?

A service is a class that encapsulates reusable logic — data fetching, business rules, logging, etc. Services are shared across components via Angular's Dependency Injection (DI) system.


Creating a Service

typescript
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; @Injectable({ providedIn: 'root' // Available application-wide (singleton) }) export class UserService { private apiUrl = '/api/users'; constructor(private http: HttpClient) {} getUsers(): Observable<User[]> { return this.http.get<User[]>(this.apiUrl); } getUserById(id: string): Observable<User> { return this.http.get<User>(\`\${this.apiUrl}/\${id}\`); } createUser(user: Partial<User>): Observable<User> { return this.http.post<User>(this.apiUrl, user); } }

Injecting a Service

typescript
@Component({ selector: 'app-user-list', template: \` <ul> <li *ngFor="let user of users">{{ user.name }}</li> </ul> \` }) export class UserListComponent implements OnInit { users: User[] = []; // Inject service via constructor constructor(private userService: UserService) {} ngOnInit() { this.userService.getUsers().subscribe(users => { this.users = users; }); } }

Modern inject() Function

typescript
import { inject } from '@angular/core'; @Component({ /* ... */ }) export class UserListComponent { private userService = inject(UserService); // No constructor needed! }

Providing Services

typescript
// 1. Root level (singleton — most common) @Injectable({ providedIn: 'root' }) export class AuthService {} // 2. Component level (new instance per component) @Component({ providers: [LoggerService] // Each component gets its own instance }) export class MyComponent {} // 3. Module level @NgModule({ providers: [AnalyticsService] }) export class AnalyticsModule {}

Injection Tokens

For non-class dependencies:

typescript
import { InjectionToken } from '@angular/core'; export const API_URL = new InjectionToken<string>('API_URL'); // Provide @NgModule({ providers: [ { provide: API_URL, useValue: 'https://api.example.com' } ] }) // Inject constructor(@Inject(API_URL) private apiUrl: string) {} // or private apiUrl = inject(API_URL);

Provider Types

ProviderDescriptionExample
useClassProvide a different class{ provide: Logger, useClass: FileLogger }
useValueProvide a static value{ provide: API_URL, useValue: 'https://...' }
useFactoryProvide via factory function{ provide: Service, useFactory: () => new Service() }
useExistingAlias to existing provider{ provide: OldService, useExisting: NewService }

Important:

Services encapsulate reusable logic and are shared via Dependency Injection. Use @Injectable({ providedIn: 'root' }) for app-wide singletons. Use the modern inject() function over constructor injection when possible. DI makes code testable (mock services in tests) and modular (swap implementations).

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.

Finished reading?
Practice Problems