Introduction

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.

Understanding PUT and DELETE Verbs in REST

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 via PUT if it does not already exist.
  • DELETE: The DELETE method is used to remove a resource. After a successful DELETE request, the resource should no longer exist on the server.
Adding PUT and DELETE to the TodoController

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:

import { Controller, Put, Delete, Param, Body } from '@nestjs/common';
import { TodoService } from './todo.service';
import { UpdateTodoDto } from './dtos/update-todo.dto';

@Controller('todos')
export class TodoController {
  constructor(private readonly todoService: TodoService) {}

  // ... POST and GET handlers removed for brevity

  // Decorate the PUT handler to require the ID in the URL for PUT /todos/:id
  @Put(':id')
  update(
    // Decorate the id parameter to declare that it comes from the URL
    @Param('id') id: string,
    
    // Decorate the todo parameter to declare that it comes from the body of the request
    @Body() todo: UpdateTodoDto,
  ) {
    return this.todoService.updateTodo(id, todo);
  }

  // Decorate the DELETE handler to require the ID in the url for DELETE /todos/:id
  @Delete(':id')
  remove(
    // Decorate the id parameter to declare that it comes from the URL
    @Param('id') id: string,
  ) {
    return this.todoService.deleteTodo(id);
  }
}
Adding edit and delete to the TodoService

Here’s the updated TodoService:

@Injectable()
export class TodoService {
  private todos: TodoDto[] = [];

  // ... existing fetch and create methods

  // update an existing Todo
  updateTodo(id: string, todo: UpdateTodoDto): TodoDto | null {
    // Start by finding the existing Todo item.  Return null if it doesn't exist.
    const todoIndex = this.todos.findIndex(todo => todo.id === id);

    if (todoIndex < 0) {
      return null;
    }

    // Modify the existing item by using all the fields of the existing item
    // and overwriting them with the updated fields.
    this.todos[todoIndex] = {
      ...this.todos[todoIndex],
      ...todo,
    };

    // Return the item we modified
    return this.todos[todoIndex];
  }

  // delete the existing Todo
  deleteTodo(id: string): void {
    // Remove the Todo by id
    this.todos = this.todos.filter(todo => todo.id !== id);
  }
}
Create the UpdateTodoDto:

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.

// The Create TodoDto only needs some basic fields
export class CreateTodoDto {
  readonly title: string;
  readonly description: string;
}

// The full Todo includes extra data like id and completed flags
export class TodoDto extends CreateTodoDto {
  readonly id: string;
  readonly completed: boolean;
}

// The Update Todo can include any non-id field
export class UpdateTodoDto {
  readonly title?: string;
  readonly description?: string;
  readonly completed?: boolean;
}
Summary and Preparation for Practice

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!

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal