I’m working on a messaging application using Node.js, Express, MongoDB, and EJS. The goal is to retrieve chat messages from MongoDB and render them using EJS. However, I’m encountering an issue where allChats
is reported as undefined in my EJS template, even though there is data in the MongoDB collection. Below are the relevant parts of my code:
Controller (controllers/chat.js
):
<code>const Message = require("../models/chat.js");
const User = require("../models/user.js");
const axios = require("axios");
require("dotenv").config();
const accessToken = process.env.ACCESS_TOKEN; // Add your access token here
const myToken = process.env.VERIFY_TOKEN;
module.exports.getChats = async (req, res) => {
const allChats = await Message.find({}).sort({ timestamp: 1 });
res.render("./chats/showMessages.ejs", { allChats });
console.error("Error retrieving chats:", error);
<code>const Message = require("../models/chat.js");
const User = require("../models/user.js");
const axios = require("axios");
require("dotenv").config();
const accessToken = process.env.ACCESS_TOKEN; // Add your access token here
const myToken = process.env.VERIFY_TOKEN;
module.exports.getChats = async (req, res) => {
try {
const allChats = await Message.find({}).sort({ timestamp: 1 });
res.json(allChats);
res.render("./chats/showMessages.ejs", { allChats });
} catch (error) {
console.error("Error retrieving chats:", error);
res.sendStatus(500);
}
};
</code>
const Message = require("../models/chat.js");
const User = require("../models/user.js");
const axios = require("axios");
require("dotenv").config();
const accessToken = process.env.ACCESS_TOKEN; // Add your access token here
const myToken = process.env.VERIFY_TOKEN;
module.exports.getChats = async (req, res) => {
try {
const allChats = await Message.find({}).sort({ timestamp: 1 });
res.json(allChats);
res.render("./chats/showMessages.ejs", { allChats });
} catch (error) {
console.error("Error retrieving chats:", error);
res.sendStatus(500);
}
};
Routes (routes/chat.js
):
<code>const express = require("express");
const router = express.Router();
const chatController = require("../controllers/chat.js");
router.get("/chats", chatController.getChats);
router.post("/send", chatController.sendMessage);
router.post("/webhook", chatController.webhook);
router.get("/webhook", chatController.verifyWebhook);
<code>const express = require("express");
const router = express.Router();
const chatController = require("../controllers/chat.js");
router.get("/chats", chatController.getChats);
router.post("/send", chatController.sendMessage);
router.post("/webhook", chatController.webhook);
router.get("/webhook", chatController.verifyWebhook);
module.exports = router;
</code>
const express = require("express");
const router = express.Router();
const chatController = require("../controllers/chat.js");
router.get("/chats", chatController.getChats);
router.post("/send", chatController.sendMessage);
router.post("/webhook", chatController.webhook);
router.get("/webhook", chatController.verifyWebhook);
module.exports = router;
EJS Template (views/showMessages.ejs
):
<code><% layout("./layouts/boilerplate") %>
<div class="row conatiner p-2">
<div class="sidebar col-4 vh-100">
<form class="d-flex" role="search">
class="form-control me-2"
<button class="btn btn-outline-success" type="submit">Search</button>
<% for(let allChat of allChats) { %>
<div class="chatItem d-flex align-items-center">
<i class="fa-solid fa-user usrIcon mb-2 me-3"></i>
<div class="chatDetails mb-2 flex-grow-1">
<div class="chatHeader d-flex justify-content-between">
<span><%= allChat.from%></span>
A snippet of a recent message sent by an user will show here...
<div class="chat-area col-8 vh-100">
<p>Chat messages will show here</p>
<code><% layout("./layouts/boilerplate") %>
<div class="row conatiner p-2">
<div class="sidebar col-4 vh-100">
<form class="d-flex" role="search">
<input
class="form-control me-2"
type="search"
placeholder="Search"
aria-label="Search"
/>
<button class="btn btn-outline-success" type="submit">Search</button>
</form>
<% for(let allChat of allChats) { %>
<div class="chatItem d-flex align-items-center">
<i class="fa-solid fa-user usrIcon mb-2 me-3"></i>
<div class="chatDetails mb-2 flex-grow-1">
<div class="chatHeader d-flex justify-content-between">
<span><%= allChat.from%></span>
<span>12:00</span>
</div>
<div class="chatMsg">
A snippet of a recent message sent by an user will show here...
</div>
</div>
</div>
<% } %>
</div>
<div class="chat-area col-8 vh-100">
<p>Chat messages will show here</p>
</div>
</div>
</code>
<% layout("./layouts/boilerplate") %>
<div class="row conatiner p-2">
<div class="sidebar col-4 vh-100">
<form class="d-flex" role="search">
<input
class="form-control me-2"
type="search"
placeholder="Search"
aria-label="Search"
/>
<button class="btn btn-outline-success" type="submit">Search</button>
</form>
<% for(let allChat of allChats) { %>
<div class="chatItem d-flex align-items-center">
<i class="fa-solid fa-user usrIcon mb-2 me-3"></i>
<div class="chatDetails mb-2 flex-grow-1">
<div class="chatHeader d-flex justify-content-between">
<span><%= allChat.from%></span>
<span>12:00</span>
</div>
<div class="chatMsg">
A snippet of a recent message sent by an user will show here...
</div>
</div>
</div>
<% } %>
</div>
<div class="chat-area col-8 vh-100">
<p>Chat messages will show here</p>
</div>
</div>
Model (models/chat.js
):
<code>const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const chatSchema = new Schema(
required: true, // Adding required to ensure messages are stored correctly
type: Schema.Types.ObjectId,
); // This will automatically add `created_at` and `updated_at` fields
const Chat = mongoose.model("Chat", chatSchema);
<code>const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const chatSchema = new Schema(
{
from: {
type: Number,
},
to: {
type: Number,
},
message: {
type: String,
required: true, // Adding required to ensure messages are stored correctly
},
contact: {
type: Schema.Types.ObjectId,
ref: "User",
},
msg_is: String,
},
{ timestamps: true }
); // This will automatically add `created_at` and `updated_at` fields
const Chat = mongoose.model("Chat", chatSchema);
module.exports = Chat;
</code>
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const chatSchema = new Schema(
{
from: {
type: Number,
},
to: {
type: Number,
},
message: {
type: String,
required: true, // Adding required to ensure messages are stored correctly
},
contact: {
type: Schema.Types.ObjectId,
ref: "User",
},
msg_is: String,
},
{ timestamps: true }
); // This will automatically add `created_at` and `updated_at` fields
const Chat = mongoose.model("Chat", chatSchema);
module.exports = Chat;
Model (models/user.js
):
<code>const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const userSchema = new Schema({
waId: { type: Number, unique: true },
module.exports = mongoose.model("User", userSchema);
<code>const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const userSchema = new Schema({
waId: { type: Number, unique: true },
name: String,
});
module.exports = mongoose.model("User", userSchema);
</code>
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const userSchema = new Schema({
waId: { type: Number, unique: true },
name: String,
});
module.exports = mongoose.model("User", userSchema);
App Initialization (app.js
):
<code>const express = require("express");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const chatRoutes = require("./routes/chat.js");
const path = require("path");
const ejsMate = require("ejs-mate");
require("dotenv").config();
const port = process.env.PORT || 3000;
app.set("view engine", "ejs");
app.set("views", path.join(__dirname, "views"));
app.engine("ejs", ejsMate);
app.use(express.static(path.join(__dirname, "./public")));
.connect(process.env.MONGODB_URI, {
useUnifiedTopology: true,
console.log("Connected to MongoDB");
console.error("Error connecting to MongoDB:", error);
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.get("/", (req, res) => {
res.render("./chats/showMessages.ejs");
app.get("/chats/new", (req, res) => {
res.render("./chats/sendMessage.ejs");
app.use("/api", chatRoutes);
app.listen(port, "0.0.0.0", () => {
console.log(`Server is listening on port ${port}`);
<code>const express = require("express");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const chatRoutes = require("./routes/chat.js");
const path = require("path");
const ejsMate = require("ejs-mate");
require("dotenv").config();
const app = express();
const port = process.env.PORT || 3000;
app.set("view engine", "ejs");
app.set("views", path.join(__dirname, "views"));
app.engine("ejs", ejsMate);
app.use(express.static(path.join(__dirname, "./public")));
// Connect to MongoDB
mongoose
.connect(process.env.MONGODB_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(() => {
console.log("Connected to MongoDB");
})
.catch((error) => {
console.error("Error connecting to MongoDB:", error);
});
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.get("/", (req, res) => {
res.render("./chats/showMessages.ejs");
});
app.get("/chats/new", (req, res) => {
res.render("./chats/sendMessage.ejs");
});
app.use("/api", chatRoutes);
//working
app.listen(port, "0.0.0.0", () => {
console.log(`Server is listening on port ${port}`);
});
</code>
const express = require("express");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const chatRoutes = require("./routes/chat.js");
const path = require("path");
const ejsMate = require("ejs-mate");
require("dotenv").config();
const app = express();
const port = process.env.PORT || 3000;
app.set("view engine", "ejs");
app.set("views", path.join(__dirname, "views"));
app.engine("ejs", ejsMate);
app.use(express.static(path.join(__dirname, "./public")));
// Connect to MongoDB
mongoose
.connect(process.env.MONGODB_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(() => {
console.log("Connected to MongoDB");
})
.catch((error) => {
console.error("Error connecting to MongoDB:", error);
});
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.get("/", (req, res) => {
res.render("./chats/showMessages.ejs");
});
app.get("/chats/new", (req, res) => {
res.render("./chats/sendMessage.ejs");
});
app.use("/api", chatRoutes);
//working
app.listen(port, "0.0.0.0", () => {
console.log(`Server is listening on port ${port}`);
});
Problem
When I navigate to the root URL /
, which should render the showMessage.ejs
template with allChats
, I get an error saying allChats is not defined
. Despite having data in my MongoDB, it seems allChats
is not being passed correctly to the EJS template.
What I’ve Tried
- Logging Data: Added console logs to check if
allChats
is populated (it shows the correct data).
- Ensured MongoDB Data: Verified that the
Message
collection has documents.
- Correct Routing: Ensured the routes are set up correctly to call
getChats
.
Expected Outcome
I expect to see a list of chat messages rendered in the showMessage.ejs
template.
Actual Outcome
The server throws an error stating allChats is not defined
when rendering the EJS template.
Request
Can someone help me identify what might be going wrong? How can I ensure allChats
is correctly passed to the EJS template for rendering?
This question provides enough context and details for someone on Stack Overflow to understand your problem and help you effectively.