Data from mongodb not displaying in view using EJS - node.js

I'm using mongoose and express along with EJS. For some reason, data I have in my mongodb is not appearing in the view. I get no errors, it's just blank.
var Person = require('.././schema.js');
module.exports = function(app) {
app.get('/about', function(req, res) {
var peopleList = [];
var title = "Users in Database:";
Person.find(function (err, people) {
if (err) return console.error(err);
for(var i = 0; i < people.length; i++) {
peopleList.push({name: people[i].name, role: people[i].role, wage: people[i].wage});
}
console.log(peopleList);
console.log(peopleList[0].name + ' ' + peopleList[0].wage + ' ' + peopleList[0].role);
});
res.render('pages/about', {
peopleList: peopleList,
title: title
});
});
}
And in my view:
<h3><%= title %></h3>
<blockquote>
<ul>
<% for(var i = 0; i < peopleList.length; i++) { %>
<li><%= peopleList[i].name %> : <%= peopleList[i].role %> : <%= peoplelist[i].wage %></li>
<% }; %>
</ul>
Alternate attempt:
<ul>
<% peopleList.forEach(function(peopleList) { %>
<li><%= peopleList.name %> - <%= peopleList.role %></li>
<% }); %>
</ul>
<%= title %> works just fine, just not the data. If I create my own array with objects in it and use the same forEach loop, it also works.

var Person = require('.././schema.js');
module.exports = function(app) {
app.get('/about', function(req, res) {
var peopleList = [];
var title = "Users in Database:";
Person.find(function (err, people) {
if (err)
return console.error(err);
for(var i = 0; i < people.length; i++)
{
peopleList.push({name: people[i].name, role: people[i].role, wage: people[i].wage});
}
console.log(peopleList);
console.log(peopleList[0].name + ' ' + peopleList[0].wage + ' ' + peopleList[0].role);
res.render('pages/about', {
peopleList: peopleList,
title: title
});
});
});
}
Please change your code to this.
Note: you should put res.render in the callback function of Person.find.

Related

How to implement pagination with mongoose and EJS and keep the search query when paging?

Im using Nodejs, EJS, Mongoose and MongoDB and i have a table that is created from the documents in my DB and cant get paging buttons to work without clearing my search query.
The way my app works is
Click on the search link which opens a search filter page.
My Search page
Then you select you filer and search. Results are then shown. With Search Query in URL
Searched Results with Search Query
3.When you click on the next page it clears your query.
Page buttons
Here is my paging buttons and below is my route
My search filters are on another page.
<div class="container">
<nav aria-label="...">
<ul class="pagination float-right">
<li class="page-item disabled">
<span class="page-link">Previous</span>
</li>
<li class="page-item active">
<a class="page-link" name="1" href="/searched/1">1</a>
</li>
<li class="page-item">
<a class="page-link" name="2" href="/searched/2">2</a>
</li>
<li class="page-item">
<a class="page-link" name="3" href="/searched/3">3</a>
</li>
<li class="page-item">
<a class="page-link">Next</a>
</li>
</ul>
</nav>
</div>
app.get("/searched/:page/:limit", function (req, res) {
if (req.isAuthenticated()) {
// const { page, limit } = req.params;
// const options = {
// sort: { dateAdded: -1 },
// page: page,
// limit: limit,
// };
const query = req.query;
if (query.btu === "") {
delete query.btu;
}
if (query.sn1 === "") {
delete query.sn1;
}
if (query.sn2 === "") {
delete query.sn2;
}
if (query.userCreated === "") {
delete query.userCreated;
}
if (query.split === "") {
delete query.split;
}
if (query.supplier === "") {
delete query.supplier;
}
if (query.issued === "") {
delete query.issued;
}
// Aircon.paginate(query, options, function (err, foundAircons) {
// if (err) {
// console.log(err);
// } else {
// console.log(foundAircons);
// res.render("instock", {
// foundAircons: foundAircons.docs,
// });
// }
// });
Aircon.find(query)
.sort({
dateAdded: "desc",
})
.exec((err, foundAircons) => {
if (err) {
console.log(err);
} else {
res.render("instock", {
foundAircons: foundAircons,
});
}
});
} else {
res.redirect("/login");
}
});
Actually, your structure looks unfamiliar to me. I'm not sure have you ever heard "pagination token" term. If you didn't you can check this magnificent guide.
I wrote searching endpoint with parameters like searchTerm, limit and pageToken to paginate. pageToken is important. If you want to go page: 2 for example. page token should be first record after the last record of the first page results. I used _id parameter in this example
Note: Creating index is mandatory for filter the records with searchTerm. Index creation is like this:
await db.collection(feedSettings._collection).createIndex({ "$**": "text" }, { name: "TextIndex" });
Code:
exports.pagination = async (req, res, next) => {
const db = await database.mongo;
const feedSettings = req.feedSettings;
// Query parameters
const limit = parseInt(req.query.limit) || 100;
let searchTerm = req.query.searchTerm;
let pageToken = req.query.pageToken;
const query = { _feedName: feedSettings.name };
// Start from last item
let paginatedQuery = {
_feedName: feedSettings.name,
_id: { $gt: ObjectID(pageToken) },
_trashed: { $ne: true }
}
// If we don't have a pageToken start from first item
if (!pageToken) {
let firstFeed = await db.collection(feedSettings._collection).findOne(query, { projection: { _id: 1 } });
if (!firstFeed) {
return res.status(200).json({
success: 1,
data: []
});
}
paginatedQuery._id = { $gte: ObjectID(firstFeed._id) };
}
// If user doesn't want to search a term in items
if (typeof searchTerm === 'string') {
await db.collection(feedSettings._collection).createIndex({ "$**": "text" }, { name: "TextIndex" });
paginatedQuery.$text = { $search: searchTerm };
}
feedsData = await db.collection(feedSettings._collection)
.find(paginatedQuery)
.limit(limit)
.toArray();
return res.status(200).json({
success: 1,
data: feedsData
});
}
managed to get it working as well with mongoose paginate v2 and found a function to rebuild the query string and pass back to the buttons
function objectToQueryString(obj) {
var str = [];
for (var p in obj)
if (obj.hasOwnProperty(p)) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
}
return str.join("&");
}
app.get("/searched", function (req, res) {
if (req.isAuthenticated()) {
const { page } = req.query;
const options = {
sort: { dateAdded: -1 },
page: !page ? 1 : page,
limit: 20,
};
const query = req.query;
delete query.page;
if (query.btu === "") {
delete query.btu;
}
if (query.sn1 === "") {
delete query.sn1;
}
if (query.sn2 === "") {
delete query.sn2;
}
if (query.userCreated === "") {
delete query.userCreated;
}
if (query.split === "") {
delete query.split;
}
if (query.supplier === "") {
delete query.supplier;
}
if (query.issued === "") {
delete query.issued;
}
var queryString = objectToQueryString(query);
console.log(queryString);
Aircon.paginate(query, options, function (err, results) {
if (err) {
console.log(err);
} else {
res.render("instock", {
foundAircons: results.docs,
total: results.totalDocs,
hasPrev: results.hasPrevPage,
hasNext: results.hasNextPage,
pageCount: results.totalPages,
page: results.page,
url: queryString,
});
}
});
} else {
res.redirect("/login");
}
});
<div class="container">
<nav aria-label="...">
<ul class="pagination float-right">
<% let prev = "disabled"; if(hasPrev){ prev = "" }; %>
<li class="page-item <%= prev %>">
<a class="page-link" href="/searched/?<%= url %>&page=<%= page - 1 %>"
>Previous</a
>
</li>
<% for(let i = 1; i <= pageCount; i++){ %> <% let active = ""; %>
<%if(page === i) { active = "active"} %>
<li class="page-item <%= active %>">
<a class="page-link" name="1" href="/searched/?<%= url %>&page=<%= i %>"
><%= i %></a
>
</li>
<% }; %> <% let next = "disabled"; if(hasNext){ next = "" }; %>
<li class="page-item <%= next %>">
<a class="page-link" href="/searched/?<%= url %>&page=<%= page + 1 %>"
>Next</a
>
</li>
</ul>
</nav>
</div>

Incorrect syntax near '?'

I have 2 drop down menus that are being populated using a query in SQL Server. Based on the selected items, I am loading a different ejs template. I have done this using the help of AJAX. However, I want to be able to load the data according to the selected criteria. For instance, if DD1 is selected as Andrew and DD2 as Date the table should load 7 columns based on those conditions.
AKA
SELECT * FROM exTable x WHERE x.Name = Andrew and x.Date = '4/22/2019
router.js
router.get('/', async (req, res) => {
try {
var name = await conn.query("SELECT DISTINCT pr.Name FROM WFS.PRTABLE pr WHERE pr.Functional_Group = 'Test'");
var dates = await conn.query('SELECT r.Date FROM WFS.Dates r');
res.render('index', {name : name , dates: dates});
} catch (err) {
res.status(500)
res.send(err.message)
}
});
router.post('/selection', async (req, res) =>{
try {
var name = await conn.query("SELECT DISTINCT pr.Name FROM WFS.PRTABLE pr WHERE pr.Group = 'Test'");
var dates = await conn.query('SELECT r.Date FROM WFS.Dates r');
var dateID = req.body.Dates;
var nameID = req.body.Names;
var tables = await conn.query("SELECT * FROM WFS.Views v WHERE v.Name = ? AND v.Date = ?", [ nameID , dateID ], function(err){
if(err) throw err;
res.render('selection', {tables: tables, name : name , dates: dates});
});
}
catch (err) {
res.status(500)
res.send(err.message)
}
});
index.ejs
<script>
$(document).ready(function(){
$('#date').on('change', function(event) {
var dates = $('#selections option:selected').val();
});
$('#name').on('change', function(event) {
var manVal = $('#selection option:selected').val();
alert(manVal);
});
$('#submitData').on('submit', function(e){
e.preventDefault();
$.ajax({
type: "POST",
url: "/selection",
data: {dates : dates , manVal: manVal},
success: function() {
alert('success');
}
});
});
});
</script>
<form action="/selection" method="POST">
<select class="DateDD" id="date" name="Dates">
<% for(var n=0; n < dates.recordset.length; n++) { %>
<option><%= dates.recordset[n].Date%></option>
<% } %>
</select>
<select class="NameDD" id="name" name="Names">
<% for(var n=0; n < name.recordset.length; n++) { %>
<option><%= name.recordset[n].Name%></option>
<% } %>
</select>
<input type="submit" name="Submit" id="submitData" class="btn btn-primary" value="View Report" />
</form>
selection.ejs
CONTAINS THE SAME THING AS INDEX.EJS (besides the <script> tag) AND ...
<table class="table table-bordered table-condensed table-striped">
<% for(var n=0; n < tables.recordset.length; n++) { %>
<tr>
<td><%=tables.recordset[n].Name%></td>
<td><%=tables.recordset[n].Date%></td>
....
....
....
....
</tr>
<% } %>
</table>
This is the error I receive: Incorrect syntax near '?' after I hit the submit button.

EJS cannot read property of undefined, how can I fix this?

My site has broken between now and last night, even though I didn't change anything. I'm making a site which grabs weather data. It's based directly on a medium article here: https://codeburst.io/build-a-weather-website-in-30-minutes-with-node-js-express-openweather-a317f904897b
Here's the server js content...
app.post('/', function (req, res) {
let city = req.body.city;
let country = req.body.country;
let url = `http://api.openweathermap.org/data/2.5/weather?q=${city}${
country.length > 0 ? "," + country : ""
}&units=imperial&appid=${api}`
request(url, function(err, response, body){
if (err) {
res.render('index',
{weather: null, error: "Please Enter Valid Location"});
}
else {
let weather = JSON.parse(body)
if (weather.main == undefined) {
res.render('index',
{weather: null, error: "Please Enter Valid Location"});
}
else {
let content = {
temp: weather.main.temp,
city: weather.name,
condition: weather.weather[0].description,
icon: "svgs/" + weather.weather[0].icon + ".svg"
}
res.render('index', {weather: content, error: null});
}
}
})
});
And here's the corresponding EJS templates...
<% if (locals.weather !== null){ %>
<p><%= locals.weather.city %></p>
<p><%= locals.weather.condition %></p>
<% } %>
<% if(error !== null){ %>
<p><%= error %></p>
<% } %>
It worked last night, but now it's saying "Cannot read property 'city' of undefined".

Elastic search is returning undefined for _id in elastic search

I am using elastic search in my application and everything works fine until you click the search result link which returns undefined. The problem I have is that the _source._id is returning undefined. So I cannot view the search result.
How can I pass the object id in /blog/article/<%= data[i]._source._id?
My code is below
router.js
router.post('/search', function(req, res, next) {
res.redirect('/search?q=' + req.body.q);
});
router.get('/search', function(req, res, next) {
if (req.query.q) {
Article.search({
query_string: { query: req.query.q}
}, function(err, results) {
results:
if (err) return next (err);
var data = results.hits.hits.map(function(hit) {
return hit;
});
res.render('main/search-result', {
query: req.query.q,
data: data
});
});
}
});
search-result.ejs
<% for (var i=0; i < data.length; i++) { %>
<div class="col-md-4">
<a href="/blog/article/<%= data[i]._source._id %>">
<div class="thumbnail">
<h3 id="data_title"><%= data[i]._source.title %></h3>
</div>
</div>
<% } %>
Finally resolved this issue by changing
<a href="/blog/article/<%= data[i]._source._id %>">
to
<a href="/blog/article/<%= data[i]._id %>">

Set object in SequelizeJS function

I'd like to get all my projects in the findAll() function of SequelizeJS but it seem's not working outside the function...
var myProjects;
Project.findAll().then(function(projects) {
myProjects = projects;
});
console.log(myProjects); // it doesn't work
EDIT #2
I'm trying to create an object containing all my links that I can get on each views without calling findAll() on each actions... projects was an example, but the real context is on my link's model !
var dbContext = require('./../../db/DbContext');
var _ = require('lodash');
var LinkDao = function () {
this.context = dbContext.entities;
};
_.extend(LinkDao.prototype, {
getAllByOrder: function (callback) {
return this.context.Link.findAll({order: 'position ASC', include: [{ model: this.context.Link}], where: {type: [0,1]}});
},
});
module.exports = LinkDao;
exports.locals = function(app){
app.use(function(request, response, next){
var linkDao = new LinkDao();
linkDao.getAllByOrder().success( function(links){
response.locals.navLinks = links;
});
var ecCategoryDao = new EcCategoryDao();
ecCategoryDao.getAll().success( function(ecCategories) {
response.locals.ecCategories = ecCategories;
next(); // navLinks is not accessible
});
});
};
<% navLinks.forEach(function(link){ %>
<% if(link.type === 0) { %>
<li><%-link.name%></li>
<li class="top-bar-divider"></li>
<% } else { %>
<li><%-link.name%></li>
<li class="top-bar-divider"></li>
<% } %>
<% }); %>

Resources