Services are plain TypeScript classes that hold logic and state meant to be shared across components. This lesson explains what services are, how to create them, and where they fit in an Angular application's architecture.
What Is an Angular Service?
A service is a class with a focused responsibility, fetching data, managing shared state, logging, or any logic that shouldn't live directly inside a component. Services become useful in Angular specifically because of dependency injection: any component (or other service) can request an instance without creating it manually.
Separating logic into services keeps components focused on presentation, and makes that logic reusable and independently testable.
providedIn: 'root' registers CartService as a singleton available application-wide through dependency injection.
Creating and Injecting a Service
@Injectable({ providedIn: 'root' })
export class MyService { }
// in a component, using inject()
private myService = inject(MyService);
// or via constructor injection
constructor(private myService: MyService) {}
@Injectable() marks a class as available for dependency injection.
providedIn: 'root' is the most common registration, making the service a singleton for the whole app.
The inject() function is the modern way to obtain a service instance inside a class field initializer.
Constructor injection is the classic approach and is still fully supported.
Angular Services Cheatsheet
The core patterns you'll use when building and consuming services.
Task
Example
Mark a class injectable
@Injectable({ providedIn: 'root' })
Generate a service
ng generate service data-store
Inject with a function
private api = inject(ApiService);
Inject via constructor
constructor(private api: ApiService) {}
Provide at component level
providers: [FeatureService] in @Component
Provide with a value
{ provide: TOKEN, useValue: config }
Provide with a factory
{ provide: TOKEN, useFactory: () => ... }
Why Use a Service Instead of a Component
Components are meant to focus on presenting UI and delegating to services for anything else: fetching data, computing derived values, managing shared state, or talking to browser APIs. Without services, every component would duplicate that logic or awkwardly reach into sibling/parent components directly.
Services are easily shared across unrelated components through dependency injection.
Services are simple to unit test since they're plain classes without a template.
Services centralize a single source of truth for shared state or business logic.
Example: A Data Access Service
One of the most common service patterns wraps HttpClient calls behind a focused, typed API, so components never call HttpClient directly.
Components inject UserService, not HttpClient directly, keeping HTTP details out of component code.
Services as a Lightweight State Container
Beyond data access, a singleton service is a natural place to hold state shared across multiple components, like the current user, a shopping cart, or UI theme preference, especially when paired with signals.
Injecting HttpClient directly into components instead of wrapping API calls in a dedicated service.
Forgetting @Injectable() on a class you intend to inject, causing a runtime dependency injection error.
Putting UI-specific logic (DOM manipulation, template state) inside a service instead of a component.
Creating a new MyService() manually instead of letting Angular's injector provide the instance.
Key Takeaways
Services are plain classes marked @Injectable() that hold shared logic and state.
providedIn: 'root' registers a service as an application-wide singleton.
Services keep components focused on presentation and make logic independently testable.
Services can hold reactive state (with signals) as well as one-off methods.
Pro Tip
Default new services to providedIn: 'root' unless you have a specific reason (like per-feature state isolation) to scope them differently, it's the simplest option and works correctly with lazy-loaded routes via tree-shakable providers.
You now understand Angular services. Next, learn about Dependency Injection, the mechanism that makes services (and much more) possible.