Mongoose - To-Do-List v2


Posted by pei_______ on 2022-06-19

mongo - $pull

mongoDB - findOneAndUpdate

lodash - capitalize


app.js

//jshint esversion:6

/* --------- 00. Basic Set Up ---------- */
const express = require("express");
const bodyParser = require("body-parser");
const _ = require("lodash");

const app = express();

app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({
  extended: true
}));
app.use(express.static("public"));


/* --------- 00. Set Up Mongoose / Schema / Model ---------- */

const mongoose = require("mongoose");
mongoose.connect("mongodb://localhost:27017/todolistDB")

const itemsSchema = new mongoose.Schema({
  name: String
});
const Item = mongoose.model("Item", itemsSchema);

const workOut = new Item({
  name: "work out"
});
const engListen = new Item({
  name: "English Listen"
});
const engReading = new Item({
  name: "English Reading"
});

const defaultItems = [workOut, engListen, engReading];

const listSchema = new mongoose.Schema({
  name: String,
  items: [itemsSchema]
})
const List = mongoose.model("List", listSchema);


/* --------- 01. Set the default Items ---------- */

app.get("/", function(req, res) {

  Item.find(function(err, foundItems) {

    // If there's nothing in the list
    if (foundItems.length == 0) {
      Item.insertMany(defaultItems, function(err) {

        if (err) {
          console.log(err);
        } else {
          console.log("Successful saved all items.");
        }
      });
      res.redirect("/");

    // If there's something in the list
    } else {
      res.render("list", {
        listTitle: "Today",
        newListItems: foundItems
      });
    }
  })
});


/* --------- 02. Set the customr Lists ---------- */

app.get("/:customListName", function(req, res) {

  // Auto capitalize the list names
  customListName = _.capitalize(req.params.customListName);

  // Check if there's already a list exist
  List.findOne({
    name: customListName
  }, function(err, foundList) {

    // If there's not a list with the name exist
    if (!foundList) {
      const customList = new List({
        name: customListName,
        items: defaultItems
      });

      // ** USE THE CALLBACK FUNCTION TO AVOID LOADING TO FAST
      customList.save(function(err, result) {
        res.redirect("/" + customListName);
      });

      // If there's already a list with the name exist
    } else {
      res.render("list", {
        listTitle: foundList.name,
        newListItems: foundList.items
      });
    }
  });
})


/* --------- 03. Add a new item in a list ---------- */

app.post("/", function(req, res) {
  const itemName = req.body.newItem;
  const listName = req.body.list;
  const newItem = new Item({
    name: itemName
  });

  // If it's add in the default list
  if (listName == "Today") {
    newItem.save();
    res.redirect("/");

  // If it's add in custom list
  } else {
    List.findOne({
      name: listName
    }, function(err, foundList) {

      // ** USE PUSH FUNCTION TO ADD IN A LIST
      foundList.items.push(newItem);
      foundList.save();
      res.redirect("/" + listName)
    })
  }
});


/* --------- 04. Delete an item in the list ---------- */

app.post("/delete", function(req, res) {
  const checkedItemId = req.body.checkbox;
  const listName = req.body.listName;

  // If the item is in default list
  if (listName == "Today") {
    Item.findByIdAndRemove(checkedItemId, function(err) {
      if (!err) {
        console.log("successful");
      };
    });
    res.redirect("/");

    // If the item is in custom list
  } else {
    // ** findOneAndUpdate function with 3 inputs:
    // 1. condition => find the List with name listName
    // 2. update
        // a. $pull the item out of list => items
        // b. the pulled out item with id => checkedItemId
    // 3. callback function => (err, foundList in condition)
    List.findOneAndUpdate({
        name: listName
      },
      {
        $pull: {
          items: {
            _id: checkedItemId
          }
        }
      },
      function(err, foundList) {
        if (!err) {
          res.redirect("/" + listName)
        }
      })
  }
});


app.get("/about", function(req, res) {
  res.render("about");
});


app.listen(3000, function() {
  console.log("Server started on port 3000");
});

list.ejs

<%- include("header") -%>

<div class="box" id="heading">
  <h1> <%= listTitle %> </h1>
</div>

<div class="box">

  <% newListItems.forEach(function(item) { %>
  <form action="/delete" method="post">
    <div class="item">
      <!-- checkbox: use onCharge attr to check if checkbox is change, then submit => POST REQUEST -->
      <!-- Add Name & Value: let app.js know what item is been checked -->
      <input type="checkbox" name="checkbox" value="<%= item._id %>" onChange="this.form.submit()">
      <p><%=  item.name  %></p>
    </div>
    <!-- hidden input: send the message back with invisible at front end -->
    <input type="hidden" name="listName" value="<%= listTitle %>">
  </form>
  <% }) %>

  <form class="item" action="/" method="post">
    <!-- autocomplete attr: Not to show the auto keyin box -->
    <input type="text" name="newItem" placeholder="New Item" autocomplete="off">
    <button type="submit" name="list"  value="<%= listTitle %>">+</button>
  </form>
</div>

<%- include("footer") -%>

#Mongoose #web系列







Related Posts

[Note] JS: DOM & DOM manipulation

[Note] JS: DOM & DOM manipulation

計算機程式語言

計算機程式語言

Laravel blade 基礎

Laravel blade 基礎


Comments