Contenuti del Corso
Introduction to Angular
Introduction to Angular
Adding Functionality to Our Application
At this stage, our application already knows how to display a list of tasks and show a message when there are none. However, users still do not have a way to enter new tasks.
We will add the ability to create a new task using a convenient button and a modal form.
We will implement:
A stylish
Add
button;A modal window with an input field for the task title;
The logic for adding a task to the list in the
TaskService
;Automatic generation of a unique identifier.
Getting Started
The first thing we need to do is enhance our TaskService
so it can create and store new tasks. The service should not only store tasks, but also handle all the business logic related to them.
We will create an addTask
method in the service. The generation of a unique ID, creation of the task object, and saving it to the list will all happen inside the service. The method will only receive a title
, which will be passed from the TaskListComponent
.
task-service
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 [...this.tasks]; } addTask(title: string) { const maxId = this.tasks.length > 0 ? Math.max(...this.tasks.map(t => t.id)) : 0; const newTask: Task = { id: maxId + 1, title: title, completed: false, }; this.tasks.push(newTask); } deleteTask(id: number) { this.tasks = this.tasks.filter(task => task.id !== id); } toggleTaskStatus(id: number) { const task = this.tasks.find(t => t.id === id); if (task) task.completed = !task.completed; } }
The addTask()
method takes only the task title and creates the Task
object internally. It first finds the maximum ID among the existing tasks, then adds 1 to it to generate a unique identifier. The new task is always set as incomplete (completed: false
) and is immediately added to the tasks
array.
This approach eliminates unnecessary logic from the component and makes the service both self-sufficient and reusable.
Updating the TaskListComponent
Now that all the logic for creating a new task has been moved into the service, the component is only responsible for receiving user input, sending the task title to the service, and refreshing the local task list. This approach simplifies the component and centralizes business logic in the TaskService
.
Inside the component, we will add two variables:
showAddTask
— a flag that controls the visibility of the modal window for adding a task;newTaskTitle
— a string to hold the task title input from the user.
We will also implement the addTask()
method, which:
Checks that the input string is not empty;
Passes the task title to the
addTask(title: string)
method of the service;Refreshes the local task list;
Clears the input field and closes the modal window.
task-component
@Component({ selector: 'app-task-list', imports: [TaskComponentComponent, CommonModule, FormsModule], templateUrl: './task-list.component.html', styleUrl: './task-list.component.css' }) export class TaskListComponent { tasks: Task[] = []; showAddTask = false; newTaskTitle = ''; constructor(private taskService: TaskService) { this.tasks = this.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.toggleTaskStatus(id); this.tasks = this.taskService.getTasks(); } }
The addTask()
method is now as simple as possible: it only handles user interaction and delegates all business logic to the service. This makes the code easier to maintain and test.
Also, make sure that FormsModule
is imported in your module, as it is necessary for two-way data binding with newTaskTitle
.
Add Button and Modal Window
Now, let's add the UI part: the Add button and the HTML markup for the modal window that includes the input field and buttons.
task-component
component-style
<div class="task-list-container"> <div class="header"> <h2>My Tasks</h2> <button class="add-button" (click)="showAddTask = true"> <span>+</span> Add </button> </div> <div class="modal-backdrop" *ngIf="showAddTask"> <div class="modal"> <h3>Add New Task</h3> <input type="text" placeholder="Task title" [(ngModel)]="newTaskTitle" /> <div class="modal-buttons"> <button class="save-button" (click)="addTask()">Save</button> <button class="cancel-button" (click)="showAddTask = false">Cancel</button> </div> </div> </div> <div *ngIf="tasks.length > 0; else noTasks"> <task-component *ngFor="let task of tasks" [task]="task" (onDelete)="deleteTask($event)" (onToggle)="toggleStatus($event)"> </task-component> </div> <ng-template #noTasks> <div class="no-tasks">No tasks yet 😊</div> </ng-template> </div>
When the user clicks the Add
button, the showAddTask
variable becomes true
, and the modal window appears. The input field is bound to the newTaskTitle
variable via [(ngModel)]
, and the button actions either save the task or close the modal without changes.
Users will be able to conveniently add tasks through a modal form. The new task immediately appears in the list without requiring a page refresh.
We have now implemented interactivity that makes our application full-featured and user-friendly for everyday use.
Grazie per i tuoi commenti!