Conditional operators in ejs - node.js

This might sound really easy. There is a very similar
answer but somehow my code is behaving abruptly and driving me crazy. I have spent last 4-5 hours on this. Any help would be great.
I am building a Socket.IO chat app using Node + Express + Passport. I want to compare the userId of the current user with that of other users connected. I want to show him all users except himself to chat with in Socket.IO.
Read comments on code for clarity :
users.js
app.get('/users', function (req, res) {
var connectedUsers = require('../app').chatUsers; // => This is an array of all logged in user and I am getting this all correctly.
if (req.isAuthenticated()) {
res.render('users', {
currentUser: req.user,
users: connectedUsers,
title: 'OnLineUsers'
});
}
});
users.ejs
<h3>CurrentUser : <%- currentUser.id %></h3> // => This Prints like **abcdefg**
<% for(var i = 0;i < users.length ; i++){ %>
<h3>UserID: <%- users[i].id %></h3> // => This also prints the same **abcdefg** if only one user is connected.
<% if( currentUser.id !== users[i].id){ %> // => But this Conditional Operator does not works and show the current user himself.
<ul>
<li>
<h3> <%= users[i].name %></h3>
<a href="/socket" id="chatRoomUrl">
<button type="submit" class="btn-success">Chat</button>
</a>
</li>
</ul>
<% } %>
<% } %>
Thanks in advance. If there is any silly mistake on my part, please excuse me for wasting your time.

Your code is fine. Maybe there is space in two property. Try :
currentUser.id.trim() !== users[i].id.trim()

Change your following line, notice the change:
<h3> <%= users[i].name %></h3>
to this:
<h3> <%- users[i].name %></h3>

Related

how to do a MongoDB query and use it in a partial view

I have a collection called events that I am currently using in my footer partial, however, I would like to show only the ones with a date greater than today. I have achieved this on mongo shell like this:
db.events.find({date: {$gte: new Date()}})
I don't understand how to use this query in footer partial where I am running a loop to show the events, I would like to save this query in a variable that I can use in the loop, and it would be visible in every page of the website as they all have the footer.
To be able to use this collection in every page I am using this code in my app.js
// passing courses to every EJS template
app.use(function (req, res, next) {
Event.find({}, function (err, allEvents) {
if (err) {
console.log(err);
res.locals.events = [];
next();
} else {
res.locals.events = allEvents;
next();
}
});
});
and this is where I am doing my loop in footer partial
<div id="event-footer" class="col-12 mt-4 mt-md-5 text-center col-md-4 text-md-left">
<div class="">
<h4 class="pb-1 pb-md-5">PROXIMOS EVENTOS</h4>
<% var count = 0; %>
<% events.forEach(function(event) { %>
<% if (count <= 2 ) { %>
<div class="eventDisplay text-center text-md-left">
<h6><%=moment(event.date).format('dddd, D MMMM, h:mm a')%></h6>
<p> <%= event.name %> </p>
</div>
<% } %>
<% count++; }); %>
</div>
</div>
Try this ...
Event.find({date: {$gte: new Date()}}, function (err, allEvents) { ...

Iterate through a MongoDB object's data

I will start off with how my mongoDB data looks like:
_id : 5c5b450918cb2b121648ff7a
name : "dannondarko"
email : "dangilmail#gmail.com"
password : "$2a$10$3z5m1e9Pcfid72Q2GchCjeTD55/SsIxmtWr3I1ZiA.DX/KlpfTbdK"
date : 2019-02-06 20:35:21.973
__v : 0
posts : Array
0 : Object
note : "test for the user dannondarko"
date : "02/08/2019"
This is just a side project and most likely will never be live so don't worry about the security of me posting this data! As for how I am procession the code in my server code:
app.get('/:username', (req, res) => {
username = req.params.username.toLowerCase();
const collection = req.app.locals.collection;
collection.find({ name: username }).toArray(function (err, results) {
if (err) {
res.status(500).send("Error communicating with the DB.");
} else if (results.length > 0) {
console.log("Here are the results: " + results);
console.log({people: results});
res.status(200).render('profile', {posts: results, name: username});
} else {
next();
}
});
});
What I am doing with this code is say you head to the address bar '/dannondarko', it should find 'dannondarko' in the collection, which it does fine, and then the 'results' variable is the complete object that I posted above. What I am trying to do is just get the 'posts' data, such as the note and date.
The note and date is the only data I need, which will be sent to this .ejs file that should create a post (kind of like FB) that shows the users' notes and date of the post. Here is my .ejs file:
<h1 class="mt-4"><%= name %></h1>
<div class="container">
<br>
<% for(var i=0; i < posts.length; i++) { %>
<div class="container">
<label><%= posts[i].note %></label>
<div class="container">
<label><%= posts[i].date %></label>
</div>
</div>
<% } %>
</div>
I hope that's enough information. I believe my downfall is not knowing how to just extract the 'posts' array from MongoDB from a certain user and iterate through the objects and sending over the note and date to the .ejs.
The results is an array of documents and you render this array to ejs as posts. Now in your ejs file posts represent the array of documents, not the posts array. So if you want to loop through all results you should edit your code like this:
<% posts.forEach(post => { %>
<h1 class="mt-4"><%= post.name %></h1>
<div class="container">
<br>
<% post.posts.forEach(p => { %>
<div class="container">
<label><%= p.note %></label>
<div class="container">
<label><%= p.date %></label>
</div>
</div>
<% }) %>
</div>
<% }) %>
If i understand well your mongo model structure the above should help you.

In Nodejs, how can i check params in Ejs render

I want to display another view if there is :id in Semantic URL
app.get(['/topic', '/topic/:id'], function(req, res){
id = req.params.id
if(id){
res.render('view',{topics:rows, topic:row[0]}
}else{
res.render('view', {topics:rows}
}
}
and view.ejs
for(var i = 0; i < topics.length; i++){
<li><%= topics[0].title%></li>
}
<% if(topic) {%>
<%= topic.description %>
<%} else {%>
<h1>Welcome</h1>
<% } %>
it did works correctly when i connect to localhost:3000/topic/1
but when i connect to localhost:3000/topic
console said topic is not defined
what is the problem?
When i use
res.render('views', {topics:rows, topic:''}
it did works correctly
Do i have to use like this?
In view.ejs it is best to check the if condition as follows. Not only in ejs but in entire javascript world
<% if(typeof topic !== 'undefined') {%>
<%= topic.description %>
<%} else {%>
<h1>Welcome</h1>
<% } %>
And you can use also use res.render('views', {topics:rows, topic:''}

Unable to display flash message in view with ejs template

I am a newbie in NodeJS. I have a problem that I am unable to show flash message in my view.
Here is my Controller,
index : function(req, res){
res.locals.flash = _.clone(req.session.flash);
res.locals.layout = false;
res.view('login');
},
login : function(req, res){
....
if(!admin){
req.session.flash = {
err : 'User is not found.' // My flash message
}
res.locals.layout = false;
res.redirect('login');
return;
}
.....
}
Here is my view,
<% if(flash && flash.err) { %>
<div class="alert alert-danger">
<% JSON.stringify(flash.err) %>
</div>
<% } %>
When login is false, it show only an empty alert box.
And I have a second problem. When I refresh page, The alert box isn't disappeared.
Could someone help me please.
Thanks a lot.
The alert box keeps on appearing because the req.session.flash object persists the session, so you need to null that out once it's used, or you can just simply use req.flash(), which does that for you. So change your index method to something like this:
index: function(req, res) {
// req.flash() returns the contents of req.session.flash and flushes it
// so it doesn't appear on next page load. No need to clone.
res.locals.flash = req.flash();
res.locals.layout = false;
res.view('login');
},
Now, onto the second problem. The error messages aren't appearing because you aren't using the proper EJS syntax to output escaped values into the view. All you need to do is change your code to this:
<% if(flash && flash.err) { %>
<div class="alert alert-danger">
// Change <% to <%=
<%= flash.err %>
</div>
<% } %>
No need to JSON.stringify, unless you like the quotes. Notice that I changed the <% to <%=, which in EJS means "escape this and output it". It's not template HTML or anything like that, so it's okay to escape it anyway.

MEAN correct way to refactor ejs express code

I've created a website with express and ejs, pulling JSON in from a file in a local file. I'd like to pass the data in from a mongo database and display with an Angular view. I have a good amount of knowledge in express, angular and mongo. Putting it all together and separating the express tasks from the angular tasks has me hung up a bit.
My app is working over in Heroku at http://healingcenter.herokuapp.com/services/ this is the page I'm unclear on how to separate the express and angular tasks.
It is currently set up in express, this was before I researched angular and the MEAN stack. below is the route config.
router.get('/services', function(req, res) {
var myServices = [];
var entireList = [];
entireList = appdata.services;
appdata.services.forEach(function(item) {
myServices = myServices.concat(item.title);
});
res.render('services', {
title: 'Services',
services: myServices,
list: entireList,
page: 'servicesList'
});
});
/* GET services detail page. */
router.get('/services/:servicesid', function(req, res) {
var myServices = [];
var entireList = [];
appdata.services.forEach(function(item){
if (item.shortname == req.params.servicesid){
entireList.push(item);
myServices = myServices.concat(item.title);
}
});
res.render('services', {
title: 'Services',
services: myServices,
list: entireList,
page: 'servicesDetail'
});
});
This is pulling in the same data.json file from the app.js file with this line of code.
app.locals.appdata = require('./data.json');
The page variable is the important part. An if else statement is customizing which data is brought in. That code is here:
<div class="services">
<% list.forEach(function(item){ %>
<article class="service group">
<% if (page!= 'servicesDetail') { %>
<h3><%= item.title %></h3>
<p><%- item.summary %></p>
more
<% }else{ %>
<a class="back" href="/services/#"><i class="fa fa-chevron-circle-left"></i> back</a>
<h3><%= item.title %></h3>
<p><%- item.description %></p>
<% } %>
</article>
<% }); %>
</div>

Resources