Skip to content

Toggle Done Status Todo Endpoint

Last but not least, we want to be able to toggle is_done for a given todo item.

We can do it by updating our index.js file and adding a new endpoint with method PUT.

const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
const bodyParser = require('body-parser');
const app = express();
const port = 3001;

app.use(cors({origin: '*'}));
app.use(bodyParser.json());

const mongoDBLink = 'mongodb+srv://test_user:Test12345@cluster0.axh68.mongodb.net/todo_list?retryWrites=true&w=majority';

mongoose.connect(mongoDBLink);

const TodoModel = mongoose.model('Todo', new mongoose.Schema({ title: String, is_done: Boolean }));

app.post('/todo', async (req, res) => {
  const { title } = req.body;

  if (!title) {
    return res.status(400).json({
      message: 'Title value cannot be empty.',
    })
  }

  try {
    const todo = new TodoModel({
      title: title,
      is_done: false,
    });

    const newTodo = await todo.save();

    return res.status(200).json({
      todo: newTodo,
    })
  } catch (e) {
    return res.status(500).json({
      message: e.message,
    })
  }
});

app.get('/todos', async (req, res) => {
  try {
    const todos = await TodoModel.find();

    return res.status(200).json({
      data: todos,
    })
  } catch (e) {
    return res.status(500).json({
      message: e.message,
    })
  }
});

app.delete('/todo/:id', async (req, res) => {
  const { id } = req.params;

  if (!id || !mongoose.Types.ObjectId.isValid(id)) {
    return res.status(400).json({
      message: 'Valid ID must be provided.',
    })
  }

  try {
    const todo = await TodoModel.findById(id);

    if (!todo) {
      return res.status(400).json({
        message: 'Todo not found.',
      })
    }

    await todo.delete();

    return res.status(200).json({})
  } catch (e) {
    return res.status(500).json({
      message: e.message,
    })
  }
});

app.put('/todo/:id', async (req, res) => {
  const { id } = req.params;

  if (!id || !mongoose.Types.ObjectId.isValid(id)) {
    return res.status(400).json({
      message: 'ID must be provided.',
    })
  }

  try {
    const todo = await TodoModel.findById(id);

    if (!todo) {
      return res.status(400).json({
        message: 'Todo not found.',
      })
    }

    todo.is_done = !todo.is_done;

    await todo.save();

    return res.status(200).json({
      todo: todo,
    })
  } catch (e) {
    return res.status(500).json({
      message: e.message,
    })
  }
});

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`);
});

As you can see, we added a new method that will be responsible for toggling is_done value of our todo items based on passed id of the specific item. Just like for deleting an itme, we covered a few cases where it should return an error.

Again, we make sure the item id is provided as a parameter and it is a valid MongoDB id.

const { id } = req.params;

if (!id || !mongoose.Types.ObjectId.isValid(id)) {
    return res.status(400).json({
      message: 'Valid ID must be provided.',
    })
}

Also, we want to check if todo item we want to update exists. If not, we will return an error an let user know that it does not.

const todo = await TodoModel.findById(id);

if (!todo) {
    return res.status(400).json({
        message: "Todo not found.",
    });
}

Then, we simply toggle is_done value, save changes to the database by calling save() function on the item and we return the successful response.

Now lets save our index.js file, restart the application and in the next part try if our toggle works as expected.


Last update: March 28, 2022