Contenuti del Corso
Introduction to Angular
Introduction to Angular
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.
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.
task-component
task-component
task-component
@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.
task-list-component
task-list-component
@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:
task-details-component
task-details-component
task-details-component
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 theid
value from the URL;Then we convert it to a number and pass it to
getTaskById(id)
from theTaskService
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.
Grazie per i tuoi commenti!