ejs for loop randering - node.js

I am sending three arrays from my node server to .ejs page and I want to display as like, Image
But I am ending up like,Image
Here is The code,
<div class="webvUI-panel__bd">
<a href="javascript:void(0);" class="webvUI-media-box webvUI-media-box_appmsg">
<% for(var i=0; i < image.length; i++) { %>
<div class="webvUI-media-box__hd">
<img class="webvUI-media-box__thumb" src="<%= image[i]%>" alt="">
</div>
<% } %>
<div class="webvUI-media-box__bd">
<% for(var i=0; i < food.length; i++) { %>
<h4 class="webvUI-media-box__title">
<%= food[i] %>
</h4>
<% } %>
<% for(var i=0; i < price.length; i++) { %>
<p class="webvUI-media-box__desc">
<%= price[i] %>$
</p>
<% } %>
</div>
</a>
</div>

Since every object has the same attributes such as image, food and price. If you define all these attributes within an object, you could group them together as in the below. Instead of sending them seperately, you can model them inside of an object and then you can loop through that object.
<div class="webvUI-panel__bd">
<a href="javascript:void(0);" class="webvUI-media-box webvUI-media-box_appmsg">
<% object.forEach(function(obj)) { %>
<div class="webvUI-media-box__hd">
<img class="webvUI-media-box__thumb" src="<%= obj.image[i]%>" alt="">
<%= obj.food[i] %>
<%= obj.price[i] %>$
</div>
<% } %>
</a>
</div>

Related

how to display array values in a list using ejs

I have an array
{"count":3,"rows":[{"p_id":"P1","gender":"M","patient_name":"a"},{"p_id":"D1","gender":"M","patient_name":"Davin"},{"p_id":"M1","gender":"M","patient_name":"Marv"}]}
Which I render from my express to my ejs file. I have a profile card in which I need to display each string in list. so for 3 strings 3 cards.
my ejs file:
<ul>
<% for(var i= 0 ; i < userData.length; i++) {%>
<li>
<span><%=userData[i].count %>
</li>
<ul>
<% for(var j=0 ; j < userData[i].rows.length; j++) {%>
<li>
<span><%=userData[i].rows[j].p_id %>
</li>
<% } %>
</ul>
<% } %>
</ul>
You haven't defined how you're rendering the EJS file so I'm going to guess that it's correct.
I'd suggest using the .forEach(...) function when looping through an array. See example below.
<% if (locals.userData) { %> <!-- Make sure userData is defined -->
<ul>
<% userData.forEach(user => { %> <!-- Loop through the array -->
<li>
<span><%= user.count %>
</li>
<ul>
<% user.rows.forEach(row => { %> <!-- Loop through the rows -->
<li>
<span><%= row.p_id %>
</li>
<% }); %>
</ul>
<% }); %>
</ul>
<% } %>

How to change <div id='<%='product'+ `${arr[i]}` %>''></div> to iterate different numbers based on collection

I'm trying to get the to add a number on the end based on the posts.length without creating duplicates.
enter code here
<h1>Home</h1>
<p> <%= startingContent %> </p>
<% let arr = []; %>
<% let i = 0; %>
<% while (i < posts.length) { %>
<% arr.push(i); %>
<% i++; %>
<% } %>
<% for(let i = 0;i < arr.length; i++) { %>
<% posts.forEach((post) => { %>
<div id='<%='product'+ `${arr[i]}` %>'>
<h1> <%= post.title %></h1>
<p> <%= post.content.substring(0, 100) + '...'; %>
<a href='/post/<%=post._id%>'>Read More</a>
</p>
</div>
<% }); %>
<% } %>
output:
<div id="product0">...</div>
<div id="product0">...</div>
<div id="product0">...</div>
<div id="product0">...</div>
<div id="product1">...</div>
...
...
etc...
What I trying to get:
<div id="product0">...</div>
<div id="product1">...</div>
<div id="product2">...</div>
<div id="product3">...</div>
Try changing this
<% for(let i = 0;i < arr.length; i++) { %>
<% posts.forEach((post) => { %>
<div id='<%='product'+ `${arr[i]}` %>'>
<h1> <%= post.title %></h1>
<p> <%= post.content.substring(0, 100) + '...'; %>
<a href='/post/<%=post._id%>'>Read More</a>
</p>
</div>
<% }); %>
<% } %>
to this
<% for(let i = 0;i < arr.length; i++) { %>
<div id='<%=`product${arr[i]}` %>'>
<% posts.forEach((post) => { %>
<h1> <%= post.title %></h1>
<p> <%= post.content.substring(0, 100) + '...'; %>
<a href='/post/<%=post._id%>'>Read More</a>
</p>
<% }); %>
</div>
<% } %>

forEach loop with if and else statements

So the title might not be the best description of my problem because I don't really know how to sum up the problem. I have a forEach loop for each event in my database and each one is classified as type = to either "trip", "ropes course", or "other". I have a section for each type of event, but I would like a way where if there are no events in the section I can not display the bannertron header and if there are no events in the whole database I can display different HTML. My code also seems very WET and I would love any suggestions on how to DRY up this page.
<% include partials/header %>
<div class="image-text">
<img src="../images/trip-photo.jpg" class="bannertron">
<div class="centered">Upcoming Trips</div>
</div>
<div class="container event">
<% events.forEach(function(event){ %>
<% if(event.type === "trip"){ %>
</br>
<h4><strong><%= event.title %></strong></h4>
<span><%= event.startdate %> - </span>
<span><%= event.enddate %></span>
<h6><strong>Location: </strong><%= event.location %></h6>
<p><%= event.description %></p>
<% if(currentUser && (currentUser.admin === true)){ %>
Edit
<form action="/calendar/<%= event._id %>?_method=DELETE" method="POST">
<button class="btn btn-danger">Delete</button>
</form>
<% } %>
<hr class="event-hr">
<% } %>
<% }); %>
</div>
<div class="image-text">
<img src="../images/climbing-photo.jpg" class="bannertron">
<div class="centered">Upcoming Climbing Days</div>
</div>
<div class="container event">
<% events.forEach(function(event){ %>
<% if(event.type === "ropescourse"){ %>
</br>
<h4><strong><%= event.title %></strong></h4>
<span><%= event.startdate %> - </span>
<span><%= event.enddate %></span>
<h6><strong>Location: </strong><%= event.location %></h6>
<p><%= event.description %></p>
<% if(currentUser && (currentUser.admin === true)){ %>
Edit
<form action="/calendar/<%= event._id %>?_method=DELETE" method="POST">
<button class="btn btn-danger">Delete</button>
</form>
<% } %>
<hr class="event-hr">
<% } %>
<% }); %>
</div>
<div class="image-text">
<img src="../images/other-photo.jpg" class="bannertron">
<div class="centered">Other Events</div>
</div>
<div class="container event">
<% events.forEach(function(event){ %>
<% if(event.type === "other"){ %>
<h4><strong><%= event.title %></strong></h4>
<span><%= event.startdate %> - </span>
<span><%= event.enddate %></span>
<h6><strong>Location: </strong><%= event.location %></h6>
<p><%= event.description %></p>
<% if(currentUser && (currentUser.admin === true)){ %>
Edit
<form action="/calendar/<%= event._id %>?_method=DELETE" method="POST">
<button class="btn btn-danger">Delete</button>
</form>
<% } %>
<hr class="event-hr">
</br>
<% } %>
<% }); %>
</div>
<% include partials/footer %>
Ideally, I would be able to loop through the events, check which type it is, put it in its respective area, and if there are none of a type, display some text like "no events scheduled" and if there are no events in total, display something else.
If this was me, I would split the events up into 3 different arrays in the node file, instead of sorting it all out inside of an ejs file. The Array.prototype.filter command would be useful for this. The nice thing about it is it returns a new array, with only items that return true for the function you pass in. It does not alter the original array, just passes a new one in. You can do something like
var trips = events.filter(function(event){
return event.type == "trip";
});
//do similar for "rope course", and for "other" you could do something like
return event.type != "trip" && event.type != "rope course"
// for the return statement.
You can do a
if(events.length == 0){
// show different html file
} else {
// show the html file with events, passing in the arrays
}
Make sure you pass all the arrays into the ejs file. For each array, you can do a similar
if(trips.length != 0){
// show banner and stuff
}
And do it for all three.
Hope this helps!

Nodejs ejs if else condition

Here i was trying for image to load, If image comes then it should show else default image. I have tried but no result
<% getdata.forEach((user) => { %>
<div class="col-md-4 col-sm-4">
<div class="service-box">
<% if ( typeof user.image == 'undefined' ) { %>
<img src="images/logo.png" class="" width='260' height='220'>
<% }else { %>
<img src="<%= user['image'] %>" class="">
<% } %>
</div>
</div>
<% }) %>
user.image may also be null or an empty string, in which case it doesn't pass your test for undefined.
Try this:
<% if (! user.image) { %>

showing MongoDB document value to EJS in a loop

I'm working on a node project. And node is very new to me so sorry if I ask a lot of stupid questions.
I'm trying to show all of my topics on my index.ejs. The root file already shows them in the console log but I can't seem to get them to show in the view.
The view already loops and knows that there are 2 topics, but the content is empty.
This is my code from the routes/index.js
router.get('/', function(req, res, next) {
Topic.find({}).exec(function(err, topic)
{
if(err){
console.log('There ware no topics');
return next(err)
}
else
{
console.log('Whoop whoop there are some topics');
res.render('index', { topic: topic } );
console.log("Logging data: " + topic);
console.log("Loggin data title out db: " + topic.topicTitle);
console.log("Loggin data desc out db: " + topic.topicDescription);
console.log("Loggin data date out db: " + topic.topicDateCreated);
}
});
});
module.exports = router;
And here is how I try to show it in my views/index.ejs
<ul>
<% for(var i = 0; i < topic.length; i++) {%>
<li>
<div class="post animated fadeInLeft">
<div class="wrap-ut pull-left">
<div class="userinfo pull-left">
<div class="avatar">
<img src="images/avatar.jpg" alt="default avatar" />
<p class="moderator"> <%= topic.fbUsername %> </p>
</div>
</div>
<div class="posttext pull-left">
<h2 class="topictitle"><a href="/topicdetail/{topic_id}" <%= topic.topicTitle %> </a></h2>
</div>
<div class="clearfix"></div>
</div>
<div class="clearfix"></div>
</div>
</li>
<% } %>
</ul>
The topic variable is an array, so you need to pass the index in order to get the proper Topic document. For instance:
<%= topic[i].fbUsername %>
Your view should look like:
<ul>
<% for(var i = 0; i < topic.length; i++) {%>
<li>
<div class="post animated fadeInLeft">
<div class="wrap-ut pull-left">
<div class="userinfo pull-left">
<div class="avatar">
<img src="images/avatar.jpg" alt="default avatar" />
<p class="moderator"> <%= topic[i].fbUsername %> </p>
</div>
</div>
<div class="posttext pull-left">
<h2 class="topictitle"> <%= topic[i].topicTitle %> </h2>
</div>
<div class="clearfix"></div>
</div>
<div class="clearfix"></div>
</div>
</li>
<% } %>
</ul>
UPDATE
You also forgot to close the tag here:
--------------------------------------------------------↴
<h2 class="topictitle"><a href="/topicdetail/{topic_id}" <%= topic[i].topicTitle %> </a></h2>
Closing the tag, I was able to see the titles:
<h2 class="topictitle"> <%= topic[i].topicTitle %> </h2>

Resources