Author Profile Altaf Shaikh
Altaf Shaikh

BE Engg | Python Dev | Content Writer | Founder of TeachMeBro | Blockchain Dev | Django

Final Todo App - Completing Routes And Controllers

January 26th 2021   368

Final Todo App - Completing Routes And Controllers
Final Todo App - Completing Routes And Controllers

We are almost done! Finally, let's implement the remaining routes and controllers, and after that we will test our API Endpoints using Postman.

Now, the process remains the same for all other routes except the logic will change, like for delete route your controller will implement the logic to delete the todo using the provided todoID.

Lets, quickly define the routes handler for all the remaining routes

Final /todos/todoRouters.js

// import express
const express = require("express");

//controllers
const {
  getAllTodos,
  createTodo,
  getTodoById,
  updateTodo,
  deleteTodo,
  taskCompletionTime,
} = require("../controllers/todoControllers");

// initialize route using express router
const todoRoute = express.Router();

// define the /todos + / => /todos/ route to get all todos
todoRoute.route("/").get(getAllTodos).post(createTodo); // same route different method chained together
todoRoute.route("/:id").get(getTodoById).put(updateTodo).delete(deleteTodo);

// export the route
module.exports = todoRoute;

Kindly ignore the error and warning in the console they all will disappear soon : D

Remaining Controllers

Create Todo Controller

// import uniquid to generate unique ids
const uniquid = require("uniquid");

const createTodo = (req, res) => {
    const { description } = req.body;
    
    Todos.create({ taskID: uniquid(), description: description})
    .then((todo) => {
      res.status(200);
      res.setHeader("Content-Type", "application/json");
      res.json({ status: "Todo added successfully", data: todo });
    })
    .catch((err) => {
      res.status(404);
      res.json({ message: "Invalid Object Property", error: err });
    });
};

Get Single Todo Controller
 

const getTodoById = (req, res) => {
  Todos.findById(req.params.id)
    .then((todo) => {
        res.status(200);
        res.setHeader("Content-Type", "application/json");
        res.json(todo);
    })
    .catch((err) => {
      res.status(404);
      res.json({ message: "Id did not exists", error: err });
    });
};

Update Todo Controller
 

const updateTodo = (req, res, next) => {
     Todos.findByIdAndUpdate(
          { _id: req.params.id },
          {
            $set: req.body,
          },
          { new: true, useFindAndModify: false } //get updated result
        )
          .then((todo) => {
            res.status(200);
            res.setHeader("Content-Type", "application/json");
            res.json(todo);
          })
          .catch((err) => {
            res.status(404);
            res.json({ message: "unable to update", error: err });
     });
};

Delete Todo Controller

const deleteTodo = (req, res, next) => {
    Todos.findByIdAndRemove(req.params.id)
        .then((response) => {
            res.status(200);
            res.setHeader("Content-Type", "application/json");
            res.json({
              status: "Todo deleted successfully",
              response: response,
            });
          })
        .catch((err) => {
            res.status(404);
            res.json({ message: "unable to delete", error: err });
      });
};

Updated Controllers - Final

/controllers/todoControllers.js

// import uniquid to generate unique ids
const uniquid = require("uniquid");

// import the todo model
const Todos = require("../models/todos");

// get all todos
const getAllTodos = (req, res) => {
  // mongoose find
  Todos.find({})
    .then((todos) => {
      res.status(200); // setting 200 ok  response status
      res.setHeader("Content-Type", "application/json"); // setting header as json
      res.json({ todos: todos }); // sending data to client in JSON
    })
    .catch((err) => {
      res.status(500); // setting 500 internal server error
      res.json({ error: err }); // sending error to client in JSON
    });
};

// create task in todo
const createTodo = (req, res) => {
  const { description } = req.body;

  Todos.create({ taskID: uniquid(), description: description })
    .then((todo) => {
      res.status(200);
      res.setHeader("Content-Type", "application/json");
      res.json({ status: "Todo added successfully", data: todo });
    })
    .catch((err) => {
      res.status(404);
      res.json({ message: "Invalid Object Property", error: err });
    });
};

// get a single todo task
const getTodoById = (req, res) => {
  Todos.findById(req.params.id)
    .then((todo) => {
      res.status(200);
      res.setHeader("Content-Type", "application/json");
      res.json(todo);
    })
    .catch((err) => {
      res.status(404);
      res.json({ message: "Id did not exists", error: err });
    });
};

// update todo task
const updateTodo = (req, res, next) => {
  Todos.findByIdAndUpdate(
    { _id: req.params.id },
    {
      $set: req.body,
    },
    { new: true, useFindAndModify: false } //get updated result
  )
    .then((todo) => {
      res.status(200);
      res.setHeader("Content-Type", "application/json");
      res.json(todo);
    })
    .catch((err) => {
      res.status(404);
      res.json({ message: "unable to update", error: err });
    });
};

// delete single todo task
const deleteTodo = (req, res, next) => {
  Todos.findByIdAndRemove(req.params.id)
    .then((response) => {
      res.status(200);
      res.setHeader("Content-Type", "application/json");
      res.json({
        status: "Todo deleted successfully",
        response: response,
      });
    })
    .catch((err) => {
      res.status(404);
      res.json({ message: "unable to delete", error: err });
    });
};

// export the controllers
module.exports = {
  getAllTodos,
  createTodo,
  getTodoById,
  updateTodo,
  deleteTodo,
};


  Browser can only performs GET request, so in order to perform POST, PUT, DELETE request we will be using industry standard tool for testing APIs i.e Postman

Lastly add following more lines into the app.js:

npm install cors

Cors module allows your frontend application to fetch data from this backend, which is running on different ORIGIN. Learn more about Browser's Same Origin Policy 

// import cors on top
const cors = require("cors");

Now below this line add the following lines
const app = express();
.
.
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: false }));

 Updated app.js 

// import express
const express = require("express");
//import mongoose
const mongoose = require("mongoose");
// import dotenv
const dotenv = require("dotenv");
const cors = require("cors");

// routers
const todoRouter = require("./routes/todoRoutes");

// load environment variable
dotenv.config({ path: ".env" });

// read env variable using process.env.<your_env_variable_name>
const PORT = process.env.PORT;
const dbURI = process.env.DATABASE_URL;

// making connection object
const connect = mongoose.connect(dbURI, {
  useNewUrlParser: true,
  useUnifiedTopology: true,
});

// connecting with database
connect.then(
  (db) => {
    console.log("Connected Successfully to Mongodb Server");
  },
  (err) => {
    console.log(err);
  }
);

// initialize express app
const app = express();

app.use(cors());
app.use(express.json());  // parse JSON data into JS object
app.use(express.urlencoded({ extended: false })); //allows you to accept form submitted data

// sending a hello response on visiting http://localhost:3000/
app.get("/", (req, res) => {
  res
    .status(200)
    .json({ message: "Hi I am Server", data: "no data on this endpoint" });
});

app.use("/todos", todoRouter);

// listening for any HTTP requests on PORT 3000
app.listen(PORT, () => {
  console.log(`Server is running at http://localhost:${PORT}`);
});

So Finally, Our Code is Completed, we had successfully created our REST API Backend using Nodejs, MongoDB, and Express. In the next section, we will test our backend using Postman

Get the Final Code on Github:

Building Todo Backend Code