Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Impara Component Communication and Navigation | Routing and Navigation 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
Component Communication and Navigation

You'll learn how to properly set up navigation within your Angular app and how to pass data between components using the URL.

We're continuing work on our Task Tracker app, where users can view a list of tasks and access detailed information for each one.

We already have two routes configured:

  • / — displays the list of all tasks;

  • /task/:id — shows details of a specific task by its ID.

Our goal now is to make it so that when the user clicks a button inside a task card, the app navigates to a details page. The TaskDetailsComponent will then retrieve the task's ID from the URL and use it to fetch the task's full data.

Note
Note

We're not passing data directly between components. Instead, we leverage Angular Router — we pass the task ID through the URL, and the component uses that ID to fetch the task from a service.

How Components Interact

Let's define how this routing interaction will work.

We'll add a button inside TaskComponent. When it's clicked, the component will emit an event to the parent component (TaskListComponent). The parent will handle the actual navigation by updating the URL, which triggers Angular to load TaskDetailsComponent for the selected task.

Why not route directly from TaskComponent?

If we ever want to reuse TaskComponent in another place (e.g., in a modal or a different list), we don't want it to be tied to routing logic. Instead, it should simply notify the parent that a navigation action is requested.

This approach is easier to test and read, keeps the routing logic centralized, and ensures that the TaskComponent remains clean and focused on its responsibilities.

Implementing TaskComponent

The main job of TaskComponent is to emit events to its parent. We'll add a button to the template that calls navigateToTask(), which will emit the event.

ts

task-component

html

task-component

css

task-component

copy
123456789101112131415161718192021222324
@Component({ selector: 'app-task', imports: [HighlightOnCompleteDirective, FormatTitlePipe, MatIconModule], templateUrl: './task.component.html', styleUrl: './task.component.css' }) export class TaskComponent { @Input() task: any; @Output() onDelete = new EventEmitter<number>(); @Output() onToggle = new EventEmitter<number>(); @Output() onNavigate = new EventEmitter<number>(); toggleStatus() { this.onToggle.emit(this.task.id); } deleteTask() { this.onDelete.emit(this.task.id); } navigateToTask() { this.onNavigate.emit(this.task.id); } }

When the user clicks the info button, the navigateToTask() method emits the task ID. This event is captured by the parent (TaskListComponent), which then handles navigation using Angular's router.

Implementing TaskListComponent

This component is responsible for navigating to the task details page.

To do this, we use Angular's built-in Router service, which lets us programmatically change the URL and load the appropriate component based on the route.

ts

task-list-component

html

task-list-component

copy
123456789101112131415161718192021222324252627282930313233343536373839
@Component({ selector: 'app-task-list', imports: [TaskComponent, CommonModule, FormsModule], templateUrl: './task-list.component.html', styleUrl: './task-list.component.css' }) export class TaskListComponent { tasks: Task[] = []; showAddTask = false newTaskTitle = '' constructor(private taskService: TaskService, private router: Router) { this.tasks = taskService.getTasks() } addTask() { const title = this.newTaskTitle.trim() if(title) { this.taskService.addTask(title) this.tasks = this.taskService.getTasks() this.newTaskTitle = '' this.showAddTask= false } } deleteTask(id: number) { this.taskService.deleteTask(id) this.tasks = this.taskService.getTasks() } toggleStatus(id: number) { this.taskService.toggleStatus(id) this.tasks = this.taskService.getTasks() } navigateToTask(id: number) { this.router.navigate(['/task', id]) } }

We added the Router service in the constructor. Angular automatically provides this service when creating the component, so no additional setup is needed.

We also set up an event listener for (onNavigate), which triggers the navigateToTask() method.

When the method is called (e.g., user clicks the info button), it builds the route /task/3, and the router updates the URL and loads the TaskDetailsComponent.

Retrieving a Task by ID in TaskDetailsComponent

When the user navigates to the /task/:id route, Angular loads the TaskDetailsComponent. This component is responsible for:

  • Getting the ID from the URL;

  • Finding the corresponding task by its ID;

  • Displaying the task details on the screen.

Here's how it works:

ts

task-details-component

html

task-details-component

css

task-details-component

copy
12345678910111213141516171819202122232425
import { Component } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { TaskService } from '../../services/task.service'; @Component({ selector: 'app-task-details', templateUrl: './task-details.component.html', styleUrl: './task-details.component.css' }) export class TaskDetailsComponent { task: Task | undefined; constructor( private route: ActivatedRoute, private taskService: TaskService, private router: Router ) { const id = Number(this.route.snapshot.paramMap.get('id')); this.task = this.taskService.getTaskById(id); } goToHomePage() { this.router.navigate(['/']); } }

Explanation:

The ActivatedRoute service lets us access the parameters of the current route.

  • We use snapshot.paramMap.get('id') to extract the id value from the URL;

  • Then we convert it to a number and pass it to getTaskById(id) from the TaskService to retrieve the task;

  • The goToHomePage() method navigates back to the main page where the full task list is displayed.

So, by using Angular Router, we've successfully set up navigation between components and passed data using a URL parameter. The TaskListComponent handles the navigation by task ID, and TaskDetailsComponent reads the ID from the route and loads the corresponding task.

Tutto è chiaro?

Come possiamo migliorarlo?

Grazie per i tuoi commenti!

Sezione 6. Capitolo 4

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
Component Communication and Navigation

You'll learn how to properly set up navigation within your Angular app and how to pass data between components using the URL.

We're continuing work on our Task Tracker app, where users can view a list of tasks and access detailed information for each one.

We already have two routes configured:

  • / — displays the list of all tasks;

  • /task/:id — shows details of a specific task by its ID.

Our goal now is to make it so that when the user clicks a button inside a task card, the app navigates to a details page. The TaskDetailsComponent will then retrieve the task's ID from the URL and use it to fetch the task's full data.

Note
Note

We're not passing data directly between components. Instead, we leverage Angular Router — we pass the task ID through the URL, and the component uses that ID to fetch the task from a service.

How Components Interact

Let's define how this routing interaction will work.

We'll add a button inside TaskComponent. When it's clicked, the component will emit an event to the parent component (TaskListComponent). The parent will handle the actual navigation by updating the URL, which triggers Angular to load TaskDetailsComponent for the selected task.

Why not route directly from TaskComponent?

If we ever want to reuse TaskComponent in another place (e.g., in a modal or a different list), we don't want it to be tied to routing logic. Instead, it should simply notify the parent that a navigation action is requested.

This approach is easier to test and read, keeps the routing logic centralized, and ensures that the TaskComponent remains clean and focused on its responsibilities.

Implementing TaskComponent

The main job of TaskComponent is to emit events to its parent. We'll add a button to the template that calls navigateToTask(), which will emit the event.

ts

task-component

html

task-component

css

task-component

copy
123456789101112131415161718192021222324
@Component({ selector: 'app-task', imports: [HighlightOnCompleteDirective, FormatTitlePipe, MatIconModule], templateUrl: './task.component.html', styleUrl: './task.component.css' }) export class TaskComponent { @Input() task: any; @Output() onDelete = new EventEmitter<number>(); @Output() onToggle = new EventEmitter<number>(); @Output() onNavigate = new EventEmitter<number>(); toggleStatus() { this.onToggle.emit(this.task.id); } deleteTask() { this.onDelete.emit(this.task.id); } navigateToTask() { this.onNavigate.emit(this.task.id); } }

When the user clicks the info button, the navigateToTask() method emits the task ID. This event is captured by the parent (TaskListComponent), which then handles navigation using Angular's router.

Implementing TaskListComponent

This component is responsible for navigating to the task details page.

To do this, we use Angular's built-in Router service, which lets us programmatically change the URL and load the appropriate component based on the route.

ts

task-list-component

html

task-list-component

copy
123456789101112131415161718192021222324252627282930313233343536373839
@Component({ selector: 'app-task-list', imports: [TaskComponent, CommonModule, FormsModule], templateUrl: './task-list.component.html', styleUrl: './task-list.component.css' }) export class TaskListComponent { tasks: Task[] = []; showAddTask = false newTaskTitle = '' constructor(private taskService: TaskService, private router: Router) { this.tasks = taskService.getTasks() } addTask() { const title = this.newTaskTitle.trim() if(title) { this.taskService.addTask(title) this.tasks = this.taskService.getTasks() this.newTaskTitle = '' this.showAddTask= false } } deleteTask(id: number) { this.taskService.deleteTask(id) this.tasks = this.taskService.getTasks() } toggleStatus(id: number) { this.taskService.toggleStatus(id) this.tasks = this.taskService.getTasks() } navigateToTask(id: number) { this.router.navigate(['/task', id]) } }

We added the Router service in the constructor. Angular automatically provides this service when creating the component, so no additional setup is needed.

We also set up an event listener for (onNavigate), which triggers the navigateToTask() method.

When the method is called (e.g., user clicks the info button), it builds the route /task/3, and the router updates the URL and loads the TaskDetailsComponent.

Retrieving a Task by ID in TaskDetailsComponent

When the user navigates to the /task/:id route, Angular loads the TaskDetailsComponent. This component is responsible for:

  • Getting the ID from the URL;

  • Finding the corresponding task by its ID;

  • Displaying the task details on the screen.

Here's how it works:

ts

task-details-component

html

task-details-component

css

task-details-component

copy
12345678910111213141516171819202122232425
import { Component } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { TaskService } from '../../services/task.service'; @Component({ selector: 'app-task-details', templateUrl: './task-details.component.html', styleUrl: './task-details.component.css' }) export class TaskDetailsComponent { task: Task | undefined; constructor( private route: ActivatedRoute, private taskService: TaskService, private router: Router ) { const id = Number(this.route.snapshot.paramMap.get('id')); this.task = this.taskService.getTaskById(id); } goToHomePage() { this.router.navigate(['/']); } }

Explanation:

The ActivatedRoute service lets us access the parameters of the current route.

  • We use snapshot.paramMap.get('id') to extract the id value from the URL;

  • Then we convert it to a number and pass it to getTaskById(id) from the TaskService to retrieve the task;

  • The goToHomePage() method navigates back to the main page where the full task list is displayed.

So, by using Angular Router, we've successfully set up navigation between components and passed data using a URL parameter. The TaskListComponent handles the navigation by task ID, and TaskDetailsComponent reads the ID from the route and loads the corresponding task.

Tutto è chiaro?

Come possiamo migliorarlo?

Grazie per i tuoi commenti!

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