Welcome to the lesson on implementing the Update and Delete handlers in a Todo REST API with NestJS. In this lesson, we'll build upon what we've learned so far to complete the CRUD functionality in our application.
Previously, you set up GET queries to fetch all Todo items or a specific item by its ID and implemented the POST handler to create new Todo items. Now, we'll focus on how to update and delete Todo items using PUT
and DELETE
requests, respectively.
In RESTful web services, HTTP methods (also known as verbs) play a crucial role in defining the actions that can be performed on resources. We've learned about GET
and POST
. Two key methods we will focus on in this lesson are PUT
and DELETE
.
- PUT: The
PUT
method is used to update the state of a resource. If the resource does not exist,PUT
can also create a new resource with the specified data, although this behavior can vary depending on implementation. In our implementation, we will not create a record viaPUT
if it does not already exist. - DELETE: The
DELETE
method is used to remove a resource. After a successfulDELETE
request, the resource should no longer exist on the server.
In NestJS, controllers handle incoming HTTP requests and send responses to the client. They typically delegate the business logic to services. For this lesson, we'll extend our TodoController
to include methods for updating and deleting Todo items.
Here's the basic structure of our updated TodoController
:
TypeScript1import { Controller, Put, Delete, Param, Body } from '@nestjs/common'; 2import { TodoService } from './todo.service'; 3import { UpdateTodoDto } from './dtos/update-todo.dto'; 4 5@Controller('todos') 6export class TodoController { 7 constructor(private readonly todoService: TodoService) {} 8 9 // ... Existing GET and PUT handlers 10 11 // Decorate the PUT handler to require the ID in the URL for PUT /todos/:id 12 @Put(':id') 13 update( 14 // Decorate the id parameter to declare that it comes from the URL 15 @Param('id') id: string, 16 17 // Decorate the todo parameter to declare that it comes from the body of the request 18 @Body() todo: UpdateTodoDto, 19 ) { 20 return this.todoService.updateTodo(id, todo); 21 } 22 23 // Decorate the DELETE handler to require the ID in the url for DELETE /todos/:id 24 @Delete(':id') 25 remove( 26 // Decorate the id parameter to declare that it comes from the URL 27 @Param('id') id: string, 28 ) { 29 return this.todoService.deleteTodo(id); 30 } 31}
Here’s the updated TodoService
:
TypeScript1@Injectable() 2export class TodoService { 3 private todos: TodoDto[] = []; 4 5 // ... existing fetch and create methods 6 7 // update an existing Todo 8 updateTodo(id: string, todo: UpdateTodoDto): TodoDto | null { 9 // Start by finding the existing Todo item. Return null if it doesn't exist. 10 const todoIndex = this.todos.findIndex(todo => todo.id === id); 11 12 if (todoIndex < 0) { 13 return null; 14 } 15 16 // Modify the existing item by using all the fields of the existing item 17 // and overwriting them with the updated fields. 18 this.todos[todoIndex] = { 19 ...this.todos[todoIndex], 20 ...todo, 21 }; 22 23 // Return the item we modified 24 return this.todos[todoIndex]; 25 } 26 27 // delete the existing Todo 28 deleteTodo(id: string): void { 29 // Remove the Todo by id 30 this.todos = this.todos.filter(todo => todo.id !== id); 31 } 32}
The UpdateTodoDto
is used when updating an existing Todo item. Unlike TodoDto
, which is for retrieving data, and CreateTodoDto
, which is for creating new items, the UpdateTodoDto
allows for partial updates of the Todo item. It contains optional properties like title
, description
, and completed
, enabling users to update any combination of these fields without needing to provide all of them. This design ensures flexibility, allowing updates to be made without overwriting data unnecessarily, while still keeping the data validation and structure consistent across the application.
TypeScript1// The Create TodoDto only needs some basic fields 2export class CreateTodoDto { 3 readonly title: string; 4 readonly description: string; 5} 6 7// The full Todo includes extra data like id and completed flags 8export class TodoDto extends CreateTodoDto { 9 readonly id: string; 10 readonly completed: boolean; 11} 12 13// The Update Todo can include any non-id field 14export class UpdateTodoDto { 15 readonly title?: string; 16 readonly description?: string; 17 readonly completed?: boolean; 18}
In this lesson, we covered how to add update and delete functionalities to our Todo REST API. We extended the TodoController
with methods to handle PUT
and DELETE
requests and implemented the corresponding business logic in the TodoService
. These additions complete our CRUD operations setup.
Now it's time for you to put what you've learned into practice. Use the CodeSignal IDE to implement and test the update and delete handlers. Congratulations on reaching the end of the course! You've built a functional Todo REST API using NestJS, a powerful framework for building server-side applications. Keep practicing, and happy coding!