Lesson 2
Setting Up Routing for Todo List
Topic Overview and Actualization

Welcome to today's lesson! We'll be delving into routing, a crucial part of developing web applications. Think of a web application's routes like a system of roads in a city, guiding data from one part to another.

Our goal today is to grasp how to set up these "roads", known as routes, using Node.js and Express for a Todo List backend. It's like giving our web application a map to handle and organize data requests.

Here's our route map for today:

  1. Understand what routes are and why they matter.
  2. Learn how to set up routes for a Todo List.
  3. Learn to handle GET, and POST HTTP methods for our routes.

Ready to start your journey? Let's hit the road!

Understanding Routes

Routes in a web application are like street addresses. Imagine you're in New York City. Each building has its unique address so people can find it among the skyscrapers. Similarly, each part of your application has an address, known as a route.

Express.js, a framework for Node.js, makes creating these routes simple. An Express route is set up like this:

JavaScript
1app.get('/todos', function(req, res) { 2 res.send('GET route on todos.'); 3});

In this snippet, app is our Express server. get is the type of HTTP method we're responding to. '/todos' is the address for our route, and function(req, res) {...} is what we do when this route is visited.

Setting Up Route Handlers for GET and POST

After setting up our routes, we need to decide what happens when each route is visited. Going back to the city analogy, it's like deciding what each building in the city does. One might be the postal office, another the city hall, and a third the cinema. These decisions are made in route handlers, where we can specify the functionality for each route.

Let's start with an example for our GET route, where we want to return the list of all todos:

JavaScript
1let todos = ["Finish Homework", "Go grocery shopping", "Prep for meeting"]; 2 3app.get('/todos', function(req, res) { 4 res.send(todos); 5});

In this route handler, req represents the incoming request data, and res is the object we can manipulate to send a response back. In this case, we've sent back our array of todos with the res.send() method. This allows the client to receive the current list of todos each time they visit this route.

Next, we need a way to store new information; after all, you cannot GET something if there is nothing to retrieve. This is done with the POST operation. Here’s a basic setup of our POST route:

JavaScript
1app.post('/todos', (req, res) => { 2});

As a server, we need to be able to comply with the requests sent to us, particularly for creating new todo items that have specific attributes. To easily access these parameters, we can instruct Express.js to automatically parse the JSON payloads into JavaScript objects by calling app.use(express.json()). This will provide us with a req.body to access the incoming data:

JavaScript
1app.use(express.json()); 2 3let todos = []; 4 5app.post('/todos', (req, res) => { 6 const newTodo = { 7 text: req.body.text, 8 done: req.body.done 9 }; 10 todos.push(newTodo); 11 res.send(newTodo); 12});

In this POST handler, we take in an object with text and done fields from the request body. We store the new todo in the server's array and send the newly created object back as a confirmation. Our backend can thus dynamically handle incoming data, keeping our todo list up-to-date. As more todos are added through POST requests, the server's array will grow, allowing for more comprehensive data retrieval with subsequent GET requests.

Finally, we can enhance our todos by giving each item a unique identifier for ease of access and control. This identifier can be set to the current time using Date.now() to avoid overlapping IDs:

JavaScript
1app.use(express.json()); 2 3let todos = []; 4 5app.post('/todos', (req, res) => { 6 const newTodo = { 7 id: Date.now(), 8 text: req.body.text, 9 done: req.body.done 10 }; 11 todos.push(newTodo); 12 res.send(newTodo); 13});

Note that the id is automatically set by the server, ensuring that each todo item has a unique identifier without requiring the requester to provide it. This makes it easier to manage and reference each todo item individually.

Error Handling and Route Protection

It's also important to account for things going wrong in our route handlers, like a missing todo, and to ensure our routes are secure. Think of the city once again: we wouldn't want unauthorized people to have access to secure buildings. This is similar to route protection:

JavaScript
1app.get('/todos/:id', function(req, res){ 2 let todoId = req.params.id; 3 4 if (!todoId) { 5 res.status(404).send('Todo not found'); // Send an error message if the id does not exist 6 } else if (!user.isLoggedIn()) { 7 res.status(403).send('Forbidden'); // Prevent unauthenticated users from deleting todos 8 } else { 9 res.send('Return the todo with id ' + todoId); 10 } 11});

In this example, user.isLoggedIn() is a symbolic placeholder used to illustrate the flow. It represents checking if a user is authenticated but is not an actual implementation.

Using Axios for HTTP Requests

To interact with our new backend routes, we will once again use Axios. Here's how you can do this.

JavaScript
1const axios = require('axios'); 2 3// Example of posting a new todo 4axios.post('http://localhost:3000/api/todos', { 5 text: 'Learn how to post in run.js', 6 done: false // set initial status of the todo 7 }) 8 .then(response => { 9 console.log('Todo created:', response.data); 10 11 // Fetch and log the updated list of todos 12 return axios.get('http://localhost:3000/api/todos'); 13 }) 14 .then(response => { 15 console.log('Updated list of todos:', response.data); 16 }) 17 .catch(error => { 18 console.error('Error:', error); 19 });

In this example, we send a POST request to add a new todo item. The payload includes the text field for the todo and a done status. The then block logs the created todo and fetches the updated list of todos. The second then block is for logging the updated list, while the catch block handles any errors.

With these examples, you can effectively interact with your backend routes using different HTTP methods and properly handle the responses and errors.

Lesson Summary

Great job! You've learned how to set up and handle routes in Express.js, making your web application more organized and functional. We've covered a lot:

  • Understanding routes
  • Setting them up for a Todo List
  • Handling different HTTP methods (GET and POST)
  • Managing errors and ensuring route protection

Take this chance to cement these skills with our practice exercises. Remember, it's just like traveling roads in a city — the more you use them, the more familiar they'll become!

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