Lesson 2
Adding ToDo Items to the List
Adding ToDo Items to the List

Welcome back! In the previous lesson, we set up the foundation of our MVC ToDo App in Symfony. We created a Todo entity, set up a TodoService to manage our todos, and defined a TodoController to handle requests and render a list of todos using Twig.

Today, we're going to add a critical feature: the ability to add new ToDo items to our list. By the end of this lesson, you will be able to create new tasks and see them displayed in the list.

Defining a Create Method in TodoService

Let's start by enhancing our TodoService to allow the creation of new ToDo items. Here is the updated code:

php
1<?php 2 3namespace App\Service; 4 5use App\Entity\Todo; 6use Symfony\Component\HttpFoundation\RequestStack; 7 8class TodoService 9{ 10 private $requestStack; 11 12 public function __construct(RequestStack $requestStack) 13 { 14 $this->requestStack = $requestStack; 15 } 16 17 private function getSession() 18 { 19 return $this->requestStack->getSession(); 20 } 21 22 public function findAll(): array 23 { 24 return $this->getSession()->get('todos', []); 25 } 26 27 public function create($title, $description = null): Todo 28 { 29 // Retrieve current list of todos from the session 30 $todos = $this->findAll(); 31 // Assign a new ID based on the count of existing todos 32 $id = count($todos) + 1; 33 // Create a new Todo object with the provided title and optional description 34 $todo = new Todo($id, $title, $description); 35 // Add new todo to the list 36 $todos[] = $todo; 37 // Save the updated list to the session 38 $this->getSession()->set('todos', $todos); 39 // Return new todo item 40 return $todo; 41 } 42}

In this updated TodoService, we'll first look at the constructor and the session access. The RequestStack provides access to the current HTTP request and session, and the getSession method retrieves the session from the request stack. Moving on to the findAll method, it fetches all the todos stored in the session, or returns an empty array if none exist.

Now, let's focus on the create method. This method starts by retrieving the current list of todos. It then assigns a new ID based on the count of existing todos. With the provided title and optional description, a new Todo object is created. Finally, the new todo is added to the list and the session is updated to save this new list.

Configuring the Create Route in the Controller

Next, we'll update our controller to handle the creation of new ToDo items. Here is the updated code for the TodoController:

php
1<?php 2 3namespace App\Controller; 4 5use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; 6use Symfony\Component\HttpFoundation\Response; 7use Symfony\Component\HttpFoundation\Request; 8use Symfony\Component\Routing\Annotation\Route; 9use App\Service\TodoService; 10 11class TodoController extends AbstractController 12{ 13 private $todoService; 14 15 public function __construct(TodoService $todoService) 16 { 17 $this->todoService = $todoService; 18 } 19 20 #[Route('/', name: 'todo_list')] 21 public function list(): Response 22 { 23 $todos = $this->todoService->findAll(); 24 return $this->render('todo/list.html.twig', ['todos' => $todos]); 25 } 26 27 #[Route('/todos/create', name: 'todo_create', methods: ['POST'])] 28 public function create(Request $request): Response 29 { 30 // Retrieve form data from request 31 $title = $request->request->get('title'); 32 $description = $request->request->get('description'); 33 // Call the create method of the TodoService to add a new ToDo item 34 $this->todoService->create($title, $description); 35 // Redirect back to the list view after successfully creating the ToDo item 36 return $this->redirectToRoute('todo_list'); 37 } 38}

In the TodoController, the constructor initializes the TodoService instance, allowing the controller to use its methods. The list method, which you've seen before, fetches all the todos and renders them using the list.html.twig template.

Let's take a closer look at the create method. The route annotation maps the URL path /todos/create to this method and specifies that it only accepts POST requests. The create method retrieves form data from the POST request, extracts the title and description, and calls the create method of the TodoService to add the new ToDo item. After successfully creating the ToDo item, the method redirects back to the list view.

Including a Form to the Template

Now, let's update our Twig template to include a form that allows users to add new ToDo items. Here is the updated list.html.twig template:

HTML, XML
1<!DOCTYPE html> 2<html> 3<head> 4 <title>ToDo List</title> 5</head> 6<body> 7 <h1>ToDo List</h1> 8 <ul> 9 {% for todo in todos %} 10 <li>{{ todo.getTitle() }} - {{ todo.getDescription() }}</li> 11 {% else %} 12 <li>No todos found</li> 13 {% endfor %} 14 </ul> 15 <!-- Form to add new ToDo items --> 16 <form action="{{ path('todo_create') }}" method="post"> 17 <input type="text" name="title" placeholder="Title" required> 18 <input type="text" name="description" placeholder="Description"> 19 <!-- Submit button to add the new ToDo item --> 20 <button type="submit">Add To Do</button> 21 </form> 22</body> 23</html>

In this template, the form's action points to the todo_create route, which we defined in the controller. The form uses the POST method to send data to the server and contains two input fields: one for the title (required) and one for the description (optional). A submit button is included to add a new ToDo item when clicked.

Example Walkthrough

Let's walk through an example of adding a new ToDo item.

  1. Fill the Form: Enter a title and an optional description in the form fields.

  2. Submit the Form: Click the Add To Do button.

  3. Form Submission: The form data is sent to the /todos/create endpoint as a POST request.

  4. Controller Handling: The TodoController extracts the form data and calls the create method of the TodoService.

  5. Service Handling: The TodoService creates a new Todo item and stores it in the session.

  6. Redirection: The controller redirects back to the list view, where the new ToDo item is now visible.

Summary and Next Steps

In this lesson, we expanded our ToDo app by adding the functionality to create new ToDo items. Here is a summary of what we've covered:

  1. Updated the TodoService: We added a create method to handle the creation of new ToDo items and save them in the session.

  2. Configured the Controller: We modified the TodoController to process form submissions and call the service method to create new ToDo items.

  3. Modified the Template: We updated the list.html.twig template to include a form for adding new ToDo items.

Now it's your turn to practice what you've learned. Head over to the practice exercises and try adding new ToDo items to your list. Remember, practice makes perfect!

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