Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Impara Creating a Custom Service in Angular | Services and Dependency Injection in Angular
Introduction to Angular
course content

Contenuti del Corso

Introduction to Angular

Introduction to Angular

1. Angular Fundamentals
2. Components and Templates
3. Mastering Angular Directives and Pipes
4. Services and Dependency Injection in Angular
5. Standalone Components & Modules
6. Routing and Navigation in Angular

book
Creating a Custom Service in Angular

You learned that services in Angular are special classes designed to move business logic out of components, making it reusable across the app.

In this chapter, you'll put that knowledge into practice by creating your own service to manage a task list.

Creating a Service

Angular provides a convenient CLI command to quickly generate a service, which sets up the necessary files and imports:

After running this command, Angular creates two files:

  • task.service.ts — the actual service file;

  • task.service.spec.ts — a test file (you can delete it).

Here's the initial content of task.service.ts:

ts

task-service

copy
12345678
import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class TaskService { constructor() {} }

The @Injectable decorator tells Angular that this service can be injected into other classes.

The providedIn: 'root' part means Angular will automatically register the service in the root module and create a single instance of it for the entire app.

Note
Definition

Singleton is a design pattern that ensures a class has only one instance and provides a global point of access to it.

Component A, Component B, or any other component — all of them will get the same instance of the service. This is super convenient because you can store shared data (like a task list) and avoid duplicating logic.

That's why a service becomes the single source of truth for a specific part of your app's logic or data. If you're curious, you can learn more about the singleton pattern in this article.

Adding Logic to the Service

Let's move on to actually building the logic for your service. Here's what you want it to do:

  • Store a list of tasks;

  • Return the task list;

  • Delete tasks;

  • Toggle the completion status of tasks.

First, let's define what a task looks like by creating a TypeScript interface:

ts

task-interface

copy
12345
export interface Task { id: number; title: string; completed: boolean; }

This interface helps clearly define the structure of a task — it includes an id, a title, and a completed status.

You haven't used interfaces before, but adding one here makes the code easier to understand and work with.

Now let's build the service that manages your task list:

ts

task-service

copy
12345678910111213141516171819202122232425262728293031323334
import { Injectable } from '@angular/core'; export interface Task { id: number; title: string; completed: boolean; } @Injectable({ providedIn: 'root' }) export class TaskService { private tasks: Task[] = [ { id: 1, title: 'Buy groceries', completed: false }, { id: 2, title: 'Walk the dog', completed: true }, { id: 3, title: 'Learn Angular', completed: false } ]; getTasks(): Task[] { // Return a copy so the original array can't be changed directly return [...this.tasks]; } deleteTask(id: number) { // Remove task by ID this.tasks = this.tasks.filter(task => task.id !== id); } toggleTaskStatus(id: number) { // Flip the completed status of a task const task = this.tasks.find(t => t.id === id); if (task) task.completed = !task.completed; } }

In this example, the task data is stored directly in the code inside a private tasks array.

To allow other parts of the application to access the task list, the getTasks() method is used. It returns a copy of the array using the spread syntax ([...]), which helps protect the original data from accidental changes.

To remove a task by its ID, the deleteTask(id: number) method is implemented. It filters the array and removes the task with the specified ID, effectively updating the list.

Another important method is toggleTaskStatus(id: number). It finds the task by its ID and toggles its completion status — if the task was marked as complete (true), it becomes incomplete (false), and vice versa.

Note
Note

You might recognize a lot of this logic from your TaskListComponent. Now, it's all moved into TaskService, which helps clean up your components and keeps your logic in one place.

This service is now the foundation that allows your components to interact with the task list — without duplicating logic.

1. Why do you create a service in Angular?

2. What does providedIn: 'root' mean in the @Injectable decorator?

3. Why do you return [...this.tasks] instead of just this.tasks in getTasks()?

question mark

Why do you create a service in Angular?

Select the correct answer

question mark

What does providedIn: 'root' mean in the @Injectable decorator?

Select the correct answer

question mark

Why do you return [...this.tasks] instead of just this.tasks in getTasks()?

Select the correct answer

Tutto è chiaro?

Come possiamo migliorarlo?

Grazie per i tuoi commenti!

Sezione 4. Capitolo 2

Chieda ad AI

expand
ChatGPT

Chieda pure quello che desidera o provi una delle domande suggerite per iniziare la nostra conversazione

course content

Contenuti del Corso

Introduction to Angular

Introduction to Angular

1. Angular Fundamentals
2. Components and Templates
3. Mastering Angular Directives and Pipes
4. Services and Dependency Injection in Angular
5. Standalone Components & Modules
6. Routing and Navigation in Angular

book
Creating a Custom Service in Angular

You learned that services in Angular are special classes designed to move business logic out of components, making it reusable across the app.

In this chapter, you'll put that knowledge into practice by creating your own service to manage a task list.

Creating a Service

Angular provides a convenient CLI command to quickly generate a service, which sets up the necessary files and imports:

After running this command, Angular creates two files:

  • task.service.ts — the actual service file;

  • task.service.spec.ts — a test file (you can delete it).

Here's the initial content of task.service.ts:

ts

task-service

copy
12345678
import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class TaskService { constructor() {} }

The @Injectable decorator tells Angular that this service can be injected into other classes.

The providedIn: 'root' part means Angular will automatically register the service in the root module and create a single instance of it for the entire app.

Note
Definition

Singleton is a design pattern that ensures a class has only one instance and provides a global point of access to it.

Component A, Component B, or any other component — all of them will get the same instance of the service. This is super convenient because you can store shared data (like a task list) and avoid duplicating logic.

That's why a service becomes the single source of truth for a specific part of your app's logic or data. If you're curious, you can learn more about the singleton pattern in this article.

Adding Logic to the Service

Let's move on to actually building the logic for your service. Here's what you want it to do:

  • Store a list of tasks;

  • Return the task list;

  • Delete tasks;

  • Toggle the completion status of tasks.

First, let's define what a task looks like by creating a TypeScript interface:

ts

task-interface

copy
12345
export interface Task { id: number; title: string; completed: boolean; }

This interface helps clearly define the structure of a task — it includes an id, a title, and a completed status.

You haven't used interfaces before, but adding one here makes the code easier to understand and work with.

Now let's build the service that manages your task list:

ts

task-service

copy
12345678910111213141516171819202122232425262728293031323334
import { Injectable } from '@angular/core'; export interface Task { id: number; title: string; completed: boolean; } @Injectable({ providedIn: 'root' }) export class TaskService { private tasks: Task[] = [ { id: 1, title: 'Buy groceries', completed: false }, { id: 2, title: 'Walk the dog', completed: true }, { id: 3, title: 'Learn Angular', completed: false } ]; getTasks(): Task[] { // Return a copy so the original array can't be changed directly return [...this.tasks]; } deleteTask(id: number) { // Remove task by ID this.tasks = this.tasks.filter(task => task.id !== id); } toggleTaskStatus(id: number) { // Flip the completed status of a task const task = this.tasks.find(t => t.id === id); if (task) task.completed = !task.completed; } }

In this example, the task data is stored directly in the code inside a private tasks array.

To allow other parts of the application to access the task list, the getTasks() method is used. It returns a copy of the array using the spread syntax ([...]), which helps protect the original data from accidental changes.

To remove a task by its ID, the deleteTask(id: number) method is implemented. It filters the array and removes the task with the specified ID, effectively updating the list.

Another important method is toggleTaskStatus(id: number). It finds the task by its ID and toggles its completion status — if the task was marked as complete (true), it becomes incomplete (false), and vice versa.

Note
Note

You might recognize a lot of this logic from your TaskListComponent. Now, it's all moved into TaskService, which helps clean up your components and keeps your logic in one place.

This service is now the foundation that allows your components to interact with the task list — without duplicating logic.

1. Why do you create a service in Angular?

2. What does providedIn: 'root' mean in the @Injectable decorator?

3. Why do you return [...this.tasks] instead of just this.tasks in getTasks()?

question mark

Why do you create a service in Angular?

Select the correct answer

question mark

What does providedIn: 'root' mean in the @Injectable decorator?

Select the correct answer

question mark

Why do you return [...this.tasks] instead of just this.tasks in getTasks()?

Select the correct answer

Tutto è chiaro?

Come possiamo migliorarlo?

Grazie per i tuoi commenti!

Sezione 4. Capitolo 2
Siamo spiacenti che qualcosa sia andato storto. Cosa è successo?
some-alt