pages.forEach() is not a function - node.js

I am trying to display a list of items from a mongodb database in a Node.js application. I am using ejs as a templating engine. I am encountering the following error on the page:
Code for router:
const express = require('express');
const router = express.Router();
// Get page model
var Page = require('../models/page');
// GET page index
router.get('/', function(req, res) {
Page.findOne({}).sort({sorting: 1}).exec(function(err, pages) {
res.render('admin/pages', {
pages: pages
});
});
});
EJS code:
<%- include('../_layouts/adminheader') %>
<h2 class="page-title">Pages</h2>
Add a new page
<br><br>
<table class="table table-striped">
<thead>
<tr>
<th>Title</th>
<th>Edit</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
<% pages.forEach(function(page) { %>
<tr>
<td><%= page.title %></td>
<td>Edit</td>
<td>Delete</td>
</tr>
<% }); %>
</tbody>
</table>
<%- include('../_layouts/adminfooter') %>

You should replace .findOne() by .find(), .findOne() only return one page object, whereas .find() return an array of objects:
Page.find({}).sort({sorting: 1}).exec(function(err, pages) {
res.render('admin/pages', {
pages: pages
});
});

Related

How to use packages in EJS template?

I'm trying to use timeago.js in an EJS template. I have tried to export the library like this:
src/lib/lib.js
const timeago = require('timeago.js');
exports.index = function(req, res){
res.render('links/list',{timeago: timeago});
}
The route is:
routes/links.js
router.get('/', (req, res)=>{
sequelize.query('SELECT * FROM links', {
type: sequelize.QueryTypes.SELECT
}).then((links)=>{
res.render('links/list', {links: links});
});
});
The EJS template is:
views/links/list.ejs
<div class="container p-4">
<div class="row">
<% for(i of links){ %>
<div class="col-md-3">
<div class="card text-center">
<div class="card-body">
<a target="_blank" href="<%= i.url %>">
<h3 class="card-title text-uppercase"><%= i.title %></h3>
</a>
<p class="m-2"><%= i.description %></p>
<h1><%= timeago.format(i.created_at); %></h1>
Delete Link
Edit
</div>
</div>
</div>
<% } %>
I need to use the library in the h1 to transform a timestamp I got from the database. However, I always get the same error: timeago is not defined.
How could I export Timeago correctly to use in EJS template? If I require the library in the routes file and send it to the EJS template through an object works perfectly, but not when I export it from another file.
I made the following test program to do a minimal test of timeago.js
const ejs = require('ejs');
const timeago = require('timeago.js');
let template = `
<% for(i of links){ %>
<h1> <%- i.created_at %>: <%- timeago.format(i.created_at) %> </h1>
<% } %>
`;
const renderData = {
links: [
{
created_at: new Date()
}
],
timeago
};
const output = ejs.render(template, renderData);
console.log(output);
Output:
<h1> Mon Sep 07 2020 00:01:57 GMT-0700 (Pacific Daylight Time): just now </h1>
So as long as you correctly pass the timeago object into your rendering data it will work.
The problem is likely here:
router.get('/', (req, res)=>{
sequelize.query('SELECT * FROM links', {
type: sequelize.QueryTypes.SELECT
}).then((links)=>{
res.render('links/list', {links: links});
});
});
Where you are not passing in the timeago object. This line:
res.render('links/list', {links: links});
Should probably be:
res.render('links/list', {links: links, timeago});
Edit:
More complete example using file paths specified in comments:
routes/links.js:
var express = require('express')
var router = express.Router();
const lib = require("../src/lib/lib");
router.get('/', (req, res)=>{
lib.index(req, res);
});
module.exports = router;
src/lib/lib.js
const timeago = require('timeago.js');
exports.index = function(req, res) {
const links = [
{
created_at: new Date()
}
];
res.render('links/list',{ timeago, links });
}

Object not found, using parse nodejs

I'm new using parse and I'm trying to get the objects from my database and displaying them with ejs using a for loop in my webpage. I'm using back4app as my database.
Here's what I'm doing:
const Car = Parse.Object.extend('Vehicle');
const query = new Parse.Query(Car);
app.get('/', function(req, res){
const VehicleInfo = [
{
VehicleName: query.get('Name'),
Description: query.get('Description'),
Price: query.get('Price'),
Rating: query.get('Rating'),
Route: query.get('Route'),
PassengerAmount: query.get('PassengerAmount')
}
]
try{
res.render('index', {
title: 'mainPage',
VehicleData: VehicleInfo
});
}catch(error){
throw error.message;
}
});
I query this and all 5 of my vehicles are displayed in the console.log but when trying to do the same in my .ejs file this shows up and only one div displays
enter image description here
Here's how I'm using the for loop
<% for (var CarInfo of VehicleData) { %>
<div class="row">
<div class="col-lg-4 col-md-6">
<!-- Car Item-->
<div class="rn-car-item">
<div class="rn-car-item-review">
<div class="fas fa-star"></div> <%= CarInfo.Rating %>
</div>
<div class="rn-car-item-thumb">
<a href="/car-single">
<img class="img-fluid" src="/images/car-1.jpg" alt="Black Sedan" srcset="/images/car-1.jpg 1x, /images/car-1#2x.jpg 2x"/>
</a>
</div>
<div class="rn-car-item-info">
<h3>
<%= CarInfo.VehicleName %>
</h3>
<p>Descripcion: <%= CarInfo.Description %></p>
<div class="rn-car-list-n-price">
<ul>
<li>Ruta: <%= CarInfo.Route %></li>
<li>Cantidad de Pasajeros: <%= CarInfo.PassengerAmount %></li>
</ul>
<div class="rn-car-price-wrap">
<a class="rn-car-price" href="/car-single">
<span class="rn-car-price-from">Desde</span>
<span class="rn-car-price-format">
<span class="rn-car-price-amount">$<%= CarInfo.Price %></span>
<span class="rn-car-price-per">/day</span>
</span>
</a>
</div>
</div>
</div>
</div>
<!-- End Car Item-->
</div>
</div>
<% } %>
I'm sure your code doesn't work like this, also not in the console. You need to run find or first in order to fetch objects.
The other problem is that your Promise hasn't been resolved and doesn't contain the result when you pass it on to the .ejs file. It works in the console because the result in the console will be updated once the Promise is resolved.
You need to do
const VehicleInfo = [];
const query = new Parse.Query(Car);
query.find().then(result => {
result.forEach(vehicle => {
VehicleInfo.push({
VehicleName: result.get('Name'),
Description: result.get('Description'),
Price: result.get('Price'),
Rating: result.get('Rating'),
Route: result.get('Route'),
PassengerAmount: query.get('PassengerAmount')
});
});
}).catch(error => {
console.error('error fetching objects', error);
});
Alternatively you can await the result for cleaner code:
app.get('/', async function(req, res) {
const VehicleInfo = [];
const query = new Parse.Query(Car);
try {
const result = await query.find();
result.forEach(vehicle => {
VehicleInfo.push({
VehicleName: result.get('Name'),
Description: result.get('Description'),
Price: result.get('Price'),
Rating: result.get('Rating'),
Route: result.get('Route'),
PassengerAmount: query.get('PassengerAmount')
});
});
} catch (error) {
console.error('error fetching objects', error);
}
});
Here's more about Promises in JavaScript

How to display mongoDB collection in html?

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>
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>

ForEach not working on mongodb but it work fine in locally array declaration

error of the code
My forEach loop is not working in ejs file while trying to fetch data from data base (mongodb) it contain a collection namely campground.but it work fine when I stored a collection of object in a array in myapp.js code.but when i m trying to implement through storing data in database it shows a error of campground.forEach is not a function
Here is my code:
myapp.js
var express=require("express");
var app=express();
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({extended:true}));
var mongoose = require('mongoose');
mongoose.connect("mongodb://localhost/campit");
var campgroundSchema=new mongoose.Schema({
name:String,
image:String
});
var campground=mongoose.model("campground",campgroundSchema);
app.get("/create",function(req,res){
campground.find({},function(err,campgrounnd){
if(err){
console.log(err);
}
else{
res.render("index.ejs",{campground:campground});
}
})
});
app.listen("3000",function(){
console.log("listening from server 3000");
});
index.ejs file which is suppose to render and it contain that for.Each loop
<div class="container">
<div class="row no-gutters">
<% campground.forEach(function(camp){ %>
<div class="col col-lg-4 img-thumbnail">
<img class="but" height="75%" width="100%" src="<%=camp.image%>" alt="image">
<div class="text-center">
<h6><%= camp.name %> </h6>
<button class="btn btn-outline-info " type="button" name="more info"> more info</button>
</div>
</div>
<% }); %>
</div>
</div>
any help will be highly appriciated..thank you
console.log the campground
The find method in MongooseJS returns a Query object (reference). There are a few ways you can do searches and return results.
campground.find().exec(function(err,result){
if(err){
console.log(err);
}
else{
res.render("index.ejs",{campground:result});
}
});
I think you are conflicting variable name
var campground=mongoose.model("campground",campgroundSchema); // here is a campground
app.get("/create",function(req,res){
campground.find({},function(err,result /* <-- */){ // the result is also campgrounnd
if(err){
console.log(err);
}
else{
res.render("index.ejs",{campground:result/* <-- */}); // pass result instead campgrounnd
}
})
});

Backbone.js and node.js : how show my data in <select></select> html

hello i am newbie in node.js and backbone.js i need u help for my development programming..
my literature : http://coenraets.org/blog/2012/10/creating-a-rest-api-using-node-js-express-and-mongodb/
i have code in :
node.js // mongodb database
server.js
app.get('/class',function(req, res) {
console.log('show all data in class');
db.collection('ak_classroom', function(err, collection) {
collection.find().toArray(function(err, items) {
res.send(items);
});
});
});
main.js
var AppRouter = Backbone.Router.extend({
routes: {
"class" : "show_class",
},
show_class: function(page) {
var p = page ? parseInt(page, 10) : 1;
var classList = new ClassCollection();
classList.fetch({success: function(){
$("#content").html(new classView({model: classList, page: p}).el);
}});
this.headerView.selectMenuItem('home-menu');
},
});
utils.loadTemplate(['show_class_View'], function() {
app = new AppRouter();
Backbone.history.start();
});
in models.js
//=== for get my link database mongodb get /class
window.class = Backbone.Model.extend({
urlRoot: "/class",
idAttribute: "_id",
//my default variable in databsae
defaults: {
_id: null,
sch_id : "",
cls_name: "",
cls_description: "",
cls_active: "",
}});
//get collection database
window.classCollection = Backbone.Collection.extend({
model: Class,
url: "/class" });
in classlist.js
window.classView = Backbone.View.extend({
initialize: function () {
this.render();
},
render: function () {
var class = this.model.models;
var len = class.length;
var startPos = (this.options.page - 1) * 100;
var endPos = Math.min(startPos + 100, len);
$(this.el).html('<table id="content"><thead><tr><th>ID School</th><th>Name class</th><th>Description</th></tr></thead></table>');
for (var i = startPos; i < endPos; i++) {
$('.content', this.el).append(new show_class_View({model: class[i]}).render().el);
}
return this;
}
});
window.show_class_View = Backbone.View.extend({
tagName: "tr",
initialize: function () {
this.model.bind("change", this.render, this);
this.model.bind("destroy", this.close, this);
},
render: function () {
$(this.el).html(this.template(this.model.toJSON()));
return this;
}
});
show_class_View.html
<table width="200" border="1">
<tbody>
<tr>
<td><%= sch_id %></td>
<td><%= cls_name %></td>
<td><%= cls_description %></td>
<td><%= cls_active %></td>
</tr>
</tbody>
</table>
this scema is sucess but my question how create data for
<select name="cls_name" value="<%= cls_name %>">
<option><%= class[i].cls_name %></option>
</select>
where in select class name in array for select data ??
i am new in backbone.js so i dont know schema ?? please help i am confusion
My first guess would be that you need to have a proper underscore templating to make your select happen. Something like this:
<script type="text/template" id="rate_select_template">
<select id="rate-selector">
<% rates.each(function(rate) { %>
<option value="<%= rate.get('duration') %>"><%= rate.get('duration') %></option>
<% }); %>
</select>
</script>
You can see a working example here:
http://jsfiddle.net/ambiguous/AEqjn/
And the underscore template doc here: http://documentcloud.github.io/underscore/#template

Resources