Reputation: 189
I am a beginner with mongoose and would like to display a mongoDB document(s) from "exColl" collection in a file called "example.ejs" in a basic html list however I have hit various problems. There are other posts on this topic yet I remain stumped by this.
-I do have a working chunk of code that outputs all documents from exColl.find({}) using res.json, obviously putting them in json format. However I have been unable to adapt this code into something that works using res.render for example.
-When I define a variable in app.js and try to access it in example.ejs the variable is not found, therefore even if I could save the results of exColl.find({}) in a variable I don't see how I would be able to enter it into the HTML
Clearly I don't know what I don't know which is very frustrating. If someone could help fill my conceptual gaps that would be fantastic.
---Edit---- Adding a snippet I have tried
app.get("/example", function (req, res){
exColl.find({})
.exec(function (err, examples){
if (err) {
res.send("an error has occurred")
} else res.render(examples: examples);
});
});
In .ejs file
<p> <%= examples %> </p>
Upvotes: 1
Views: 8570
Reputation: 26930
Your problem seems to be the EJS syntax which you should review here: EJS Docs. Consider the following test project structure:
.
├── index.js
├── package.json
├── setup.js
└── views
├── index.ejs
└── table.ejs
I create a test DB with setup.js so that we have some dummy posts to display:
const mongoose = require("mongoose");
mongoose.connect("mongodb://localhost:8081/test", {
useNewUrlParser: true
});
const Post = mongoose.model("Post", {
title:String,
body: String
});
const toMake = [
{title: "hello", body: "world"},
{title: "foo", body: "bar"},
{title: "fizz", body: "buzz"},
{title: "a", body: "b"}
];
Post.insertMany(toMake)
.then(()=>{
console.log("done");
mongoose.connection.close();
})
.catch(err => console.error(err));
I create an EJS template views/table.ejs to render my posts as a table:
<table>
<thead>
<tr>
<th>Title</th>
<th>Body</th>
</tr>
</thead>
<tbody>
<% posts.forEach(post => { %>
<tr>
<td><%= post.title %></td>
<td><%= post.body %></td>
</tr>
<% }) %>
</tbody>
</table>
I then create an EJS template views/index.ejs to use the table template
<main>
<h1>Posts</h1>
<%- include("table", {posts}); %>
</main>
I also make a server to respond to requests in index.js and run it with node index.js
:
const express = require("express");
const mongoose = require("mongoose");
mongoose.connect("mongodb://localhost:8081/test", {
useNewUrlParser: true
});
const app = express();
const Post = mongoose.model("Post", {
title: String,
body: String
});
app.set("view engine", "ejs");
app.get("/", async (req, res) => {
const posts = await Post.find({});
res.render("index", {posts});
});
app.listen(3000, () => console.log("Listening"));
And when I curl localhost:3000
I get the rendered HTML:
<main>
<h1>Posts</h1>
<table>
<thead>
<tr>
<th>Title</th>
<th>Body</th>
</tr>
</thead>
<tbody>
<tr>
<td>hello</td>
<td>world</td>
</tr>
<tr>
<td>foo</td>
<td>bar</td>
</tr>
<tr>
<td>fizz</td>
<td>buzz</td>
</tr>
<tr>
<td>a</td>
<td>b</td>
</tr>
</tbody>
</table>
</main>
No matter what, I will need to feed data to the res.render()
function and populate the render scope with all the data needed to render.
However, I have made table.ejs reusable. So lets say that I have another page that I want to be able to show some of the posts in a tabular fashion.
I have another EJS template: views/profile.ejs that looks like this:
<main>
<h1>2 Posts</h1>
<%- include("table", {posts: posts.slice(0, 2)}); %>
</main>
And I add another route to my application at /sliced
:
app.get("/sliced", async (req, res) => {
const posts = await Post.find({});
res.render("profile", {posts});
});
Whenever I curl localhost:3000/sliced
I get only the first 2 items in the posts since I only populated the include
's scope with a slice of all the posts:
<main>
<h1>2 Posts</h1>
<table>
<thead>
<tr>
<th>Title</th>
<th>Body</th>
</tr>
</thead>
<tbody>
<tr>
<td>hello</td>
<td>world</td>
</tr>
<tr>
<td>foo</td>
<td>bar</td>
</tr>
</tbody>
</table>
</main>
Upvotes: 2