Lesson 2
Create a ToDo Item Provided from the Request Body
Creating new Todo Items

Welcome to this lesson on creating a ToDo item provided from the request body using NestJS. So far, you have learned how to handle GET requests to fetch all ToDo items and fetch a single ToDo item by its ID. In this lesson, we'll expand on that by focusing on how to create a new ToDo item using a POST request. We will dive into the details of the controller and service layers, as well as using Data Transfer Objects (DTOs).

A POST request is a type of HTTP request method used within the context of RESTful APIs to send data to a server to create a new resource. In REST architecture, POST requests are utilized to submit data enclosed in the request body (as opposed to data in the URL) to a specified endpoint, which processes the data and creates a new resource. This method is typically used to create new entries in a database, such as adding a new Todo item to a Todo list. The server then processes this information and often responds with a representation of the newly created resource, including any additional data the server has added, like a unique identifier.

What's the difference between GET and POST?

Unlike GET requests, which retrieve data, POST requests send data within the request body to a server endpoint, where it is processed and used to create a new resource, such as adding a new Todo item to a list. While a GET request might fetch the current list of Todo items or details of a specific item, a POST request is used to submit new information, like a new task, which the server stores in the database. We often like to talk in the terms of mutating (changing) data. In a REST API, it is typical for GET requests to query data but not mutate it. POST requests (and similar PUT and DELETE requests which we'll learn about in the next lesson) mutate the data. Because of this, you'll often hear people refer to queries and mutations in an API.

Understanding the TodoController

The controller in our NestJS application handles incoming HTTP requests and sends responses. In this case, the TodoController will manage our POST requests for creating new ToDo items.

Here’s a detailed breakdown of the provided TodoController code snippet:

TypeScript
1@Controller('todos') 2export class TodoController { 3 constructor(private readonly todoService: TodoService) {} 4 5 // ... Existing GET handlers 6 7 @Post() // Decorate the create method to declare that this handles POST requests 8 create( 9 // Decorate this data object with @Body() to declare that the data comes 10 // from the HTTP body and not the URL 11 @Body() todo: CreateTodoDto, 12 ): TodoDto { 13 return this.todoService.createTodo(todo); 14 } 15}

This controller sets up our route to handle the creation of ToDo items.

Implementing the TodoService

The TodoService handles our business logic – in this case, creating new ToDo items. Let’s delve into the provided TodoService code snippet:

TypeScript
1@Injectable() 2export class TodoService { 3 private todos: TodoDto[] = []; 4 5 // ... Existing fetch methods 6 7 createTodo(todo: CreateTodoDto): TodoDto { 8 // The CreateTodoDto is a subset of the TodoDto. It only includes the title 9 // and description so we need to populate the id and the completed fields. 10 const newTodo = { 11 id: Date.now().toString(), 12 ...todo, 13 completed: false, 14 }; 15 16 // Add the new Todo to the collection 17 this.todos.push(newTodo); 18 19 // Return the new Todo that we created. 20 return newTodo; 21 } 22}

The service layer encapsulates our application's business logic and keeps the controller layer lean.

Creating Data Transfer Objects (DTOs)

DTOs are used to define the structure of data being transferred and perform validation. Here, we use two DTOs:

TodoDto

The TodoDto defines the structure of a Todo item when retrieving data, specifically for GET requests. It ensures that whenever a ToDo item is fetched, it has the required properties like id, title, description, and completed. By defining these fields explicitly, we ensure consistency in the data format across different parts of the application.

TypeScript
1export class TodoDto { 2 readonly id: string; 3 readonly title: string; 4 readonly description: string; 5 readonly completed: boolean; 6}

DTOs help ensure that the data follows a predefined structure, making the application more robust and secure.

CreateTodoDto

The CreateTodoDto is used when creating a new Todo item, particularly for POST requests. Unlike TodoDto, this class is a subset of the data, containing only the properties that are relevant when creating a new Todo: the title and description. This design prevents users from sending unnecessary or potentially dangerous fields like id or completed, which are instead managed in the TodoService.

TypeScript
1export class CreateTodoDto { 2 readonly title: string; 3 readonly description: string; 4}
Review, Summary, and Preparing for Practice

In this lesson, we covered how to create a new ToDo item from a request body using NestJS. We explored the roles of the controller and service layers, the importance of DTOs in defining data structures, and walked through a practical example of creating a ToDo item using a POST request.

Here’s a quick recap:

  • The TodoController handles the POST request and calls the service method.
  • The TodoService contains the business logic to create and store the new ToDo item.
  • DTOs ensure the integrity and structure of the data being transferred.

Up next, you’ll have the opportunity to practice these concepts through hands-on exercises. This practice will help solidify your understanding and give you the confidence to build and expand a ToDo REST API using NestJS.

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.