TypeError: Cannot read properties of null (reading 'items')
TypeError: Cannot read properties of null (reading 'items')
错误:抛出错误; // 未处理的 'error' 事件
TypeError: 无法读取 null 的属性(读取 'items')
在 C:\Users\shiva\Desktop\Web Development\todolist\app.js:105:17
getting the error in the 1st app.post method -> else statement. stuck at it for almost a day.
ps: code might not run as db link is changed by me
const express = require("express");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const _ = require("lodash");
const app = express();
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({extended: true}));
app.use(express.static("public"));
mongoose.connect("mongodb+srv://adminshivam:refd3sfde@cluster0.3igye.mongodb.net/todolistDB");
const itemsSchema = {
name: String
};
const Item = mongoose.model("Item", itemsSchema);
const item1 = new Item({
name: "Welcome to your todolist!"
});
const item2 = new Item({
name: "Hit the + button to add a new item."
});
const item3 = new Item({
name: "<-- Hit this to delete an item."
});
const defaultItems = [item1, item2, item3];
const listSchema = {
name: String,
items: [itemsSchema]
};
const List = mongoose.model("List", listSchema);
app.get("/", function(req, res) {
Item.find({}, function(err, foundItems){
if (foundItems.length === 0) {
Item.insertMany(defaultItems, function(err){
if (err) {
console.log(err);
} else {
console.log("Successfully savevd default items to DB.");
}
});
res.redirect("/");
} else {
res.render("list", {listTitle: "Today", newListItems: foundItems});
}
});
});
app.get("/:customListName", function(req, res){
const customListName = _.capitalize(req.params.customListName);
List.findOne({name: customListName}, function(err, foundList){
if (!err){
if (!foundList){
//Create a new list
const list = new List({
name: customListName,
items: defaultItems
});
list.save();
res.redirect("/" + customListName);
} else {
//Show an existing list
res.render("list", {listTitle: foundList.name, newListItems: foundList.items});
}
}
});
});
app.post("/", function(req, res){
const itemName = req.body.newItem;
const listName = req.body.list;
const item = new Item({
name: itemName
});
if (listName === "Today"){
item.save();
res.redirect("/");
} else {
List.findOne({name: listName}, function(err, foundList){
foundList.items.push(item);
foundList.save();
res.redirect("/" + listName);
});
}
});
app.post("/delete", function(req, res){
const checkedItemId = req.body.checkbox;
const listName = req.body.listName;
if (listName === "Today") {
Item.findByIdAndRemove(checkedItemId, function(err){
if (!err) {
console.log("Successfully deleted checked item.");
res.redirect("/");
}
});
} else {
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");
});
error link from above code
foundList.items.push(item);
list.ejs
<%- include("header") -%>
<div class="box" id="heading">
<h1> <%= listTitle %> </h1>
</div>
<div class="box">
<% newListItems.forEach((listItem) => { %>
<form action="/delete" method="post">
<div class="item">
<input type="checkbox" name="checkbox" value="<%= listItem._id %>" onChange="this.form.submit()">
<p><%= listItem.name %></p>
</div>
<input type="hidden" name="listName" value="<%= listTitle %>"></input>
</form>
<% });%>
<form class="item" action="/" method="post">
<input type="text" name="newItem" placeholder="New Item" autocomplete="off">
<button type="submit" name="list" value="<%= listTitle %> ">+</button>
</form>
</div>
<%- include("footer") -%>
问题似乎出在您的架构上,您没有按照正确的方式进行操作,而不是像这样将对象传递给 moongose.model
:
const itemsSchema = {
name: String
};
const Item = mongoose.model("Item", itemsSchema);
您应该使用来自 mongoose 的 class Schema
创建一个模式,因此请尝试以下操作:
const mongoose = require("mongoose");
const { Schema } = mongoose
const itemsSchema = new Schema({
name: {type: String, required: true}
})
const Item = mongoose.model("Item", itemsSchema)
然后在您的 listSchema
中执行以下操作:
// removed const defaultItems = [item1, item2, item3];
const listSchema = new Schema({
name: {type: String, required: true},
// define an array of id that references the Item schema
items: [{type: ObjectId, ref: "Item", required: true, default: [] }]
});
const List = mongoose.model("List", listSchema);
// the object named as list1 will contain a reference to id of item1, item2 and item3.
const list1 = new List({name: "list1", items: [item1._id, item2._id, item3._id]}).save()
更进一步,在您的 post api
中:
app.post("/", async function(req, res){
const itemName = req.body.newItem;
const listName = req.body.list;
try {
const item = new Item({ name: itemName });
if (listName === "Today") {
await item.save();
res.redirect("/");
} else {
// save the item id to items field from list schema
const list = await List.findOne({ name: listName })
list.items.push(item._id)
await list.save()
// don't make a redirect within the database query
res.redirect("/" + listName);
}
} catch(err) {
// If some error was threw handle it here
// you can handle mongoose errors as follow:
if(err instanceof mongoose.Error) {
// use a custom message or err.message
res.status(500).json({message: "error with Db"})
}
res.status(500).json({message: "something went wrong"})
}
});
也可以从 mongoose 查看 the docs to know more about it, as you are using references between your schemas I suggest you to take a look at the populate method because probably you will need it in the future. See the available queries,几乎所有你需要的都在文档中。希望对你有所帮助!
错误:抛出错误; // 未处理的 'error' 事件
TypeError: 无法读取 null 的属性(读取 'items') 在 C:\Users\shiva\Desktop\Web Development\todolist\app.js:105:17
getting the error in the 1st app.post method -> else statement. stuck at it for almost a day. ps: code might not run as db link is changed by me
const express = require("express");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const _ = require("lodash");
const app = express();
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({extended: true}));
app.use(express.static("public"));
mongoose.connect("mongodb+srv://adminshivam:refd3sfde@cluster0.3igye.mongodb.net/todolistDB");
const itemsSchema = {
name: String
};
const Item = mongoose.model("Item", itemsSchema);
const item1 = new Item({
name: "Welcome to your todolist!"
});
const item2 = new Item({
name: "Hit the + button to add a new item."
});
const item3 = new Item({
name: "<-- Hit this to delete an item."
});
const defaultItems = [item1, item2, item3];
const listSchema = {
name: String,
items: [itemsSchema]
};
const List = mongoose.model("List", listSchema);
app.get("/", function(req, res) {
Item.find({}, function(err, foundItems){
if (foundItems.length === 0) {
Item.insertMany(defaultItems, function(err){
if (err) {
console.log(err);
} else {
console.log("Successfully savevd default items to DB.");
}
});
res.redirect("/");
} else {
res.render("list", {listTitle: "Today", newListItems: foundItems});
}
});
});
app.get("/:customListName", function(req, res){
const customListName = _.capitalize(req.params.customListName);
List.findOne({name: customListName}, function(err, foundList){
if (!err){
if (!foundList){
//Create a new list
const list = new List({
name: customListName,
items: defaultItems
});
list.save();
res.redirect("/" + customListName);
} else {
//Show an existing list
res.render("list", {listTitle: foundList.name, newListItems: foundList.items});
}
}
});
});
app.post("/", function(req, res){
const itemName = req.body.newItem;
const listName = req.body.list;
const item = new Item({
name: itemName
});
if (listName === "Today"){
item.save();
res.redirect("/");
} else {
List.findOne({name: listName}, function(err, foundList){
foundList.items.push(item);
foundList.save();
res.redirect("/" + listName);
});
}
});
app.post("/delete", function(req, res){
const checkedItemId = req.body.checkbox;
const listName = req.body.listName;
if (listName === "Today") {
Item.findByIdAndRemove(checkedItemId, function(err){
if (!err) {
console.log("Successfully deleted checked item.");
res.redirect("/");
}
});
} else {
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");
});
error link from above code
foundList.items.push(item);
list.ejs
<%- include("header") -%>
<div class="box" id="heading">
<h1> <%= listTitle %> </h1>
</div>
<div class="box">
<% newListItems.forEach((listItem) => { %>
<form action="/delete" method="post">
<div class="item">
<input type="checkbox" name="checkbox" value="<%= listItem._id %>" onChange="this.form.submit()">
<p><%= listItem.name %></p>
</div>
<input type="hidden" name="listName" value="<%= listTitle %>"></input>
</form>
<% });%>
<form class="item" action="/" method="post">
<input type="text" name="newItem" placeholder="New Item" autocomplete="off">
<button type="submit" name="list" value="<%= listTitle %> ">+</button>
</form>
</div>
<%- include("footer") -%>
问题似乎出在您的架构上,您没有按照正确的方式进行操作,而不是像这样将对象传递给 moongose.model
:
const itemsSchema = {
name: String
};
const Item = mongoose.model("Item", itemsSchema);
您应该使用来自 mongoose 的 class Schema
创建一个模式,因此请尝试以下操作:
const mongoose = require("mongoose");
const { Schema } = mongoose
const itemsSchema = new Schema({
name: {type: String, required: true}
})
const Item = mongoose.model("Item", itemsSchema)
然后在您的 listSchema
中执行以下操作:
// removed const defaultItems = [item1, item2, item3];
const listSchema = new Schema({
name: {type: String, required: true},
// define an array of id that references the Item schema
items: [{type: ObjectId, ref: "Item", required: true, default: [] }]
});
const List = mongoose.model("List", listSchema);
// the object named as list1 will contain a reference to id of item1, item2 and item3.
const list1 = new List({name: "list1", items: [item1._id, item2._id, item3._id]}).save()
更进一步,在您的 post api
中:
app.post("/", async function(req, res){
const itemName = req.body.newItem;
const listName = req.body.list;
try {
const item = new Item({ name: itemName });
if (listName === "Today") {
await item.save();
res.redirect("/");
} else {
// save the item id to items field from list schema
const list = await List.findOne({ name: listName })
list.items.push(item._id)
await list.save()
// don't make a redirect within the database query
res.redirect("/" + listName);
}
} catch(err) {
// If some error was threw handle it here
// you can handle mongoose errors as follow:
if(err instanceof mongoose.Error) {
// use a custom message or err.message
res.status(500).json({message: "error with Db"})
}
res.status(500).json({message: "something went wrong"})
}
});
也可以从 mongoose 查看 the docs to know more about it, as you are using references between your schemas I suggest you to take a look at the populate method because probably you will need it in the future. See the available queries,几乎所有你需要的都在文档中。希望对你有所帮助!