Cannot read property 'forEach' of undefined node.js - node.js

I am getting a .forEach() error on this code
```<% if(locals.isAuthenticated) { %>
<section>
<h4>Leave a comment</h4>
<form method="POST" action="/landmarks/<%= landmark.id %>/comments">
<textarea name="content" id="content" placeholder="Comment"></textarea>
<button class="button">Leave a comment</button>
</form>
</section>
<% } %>
<section>
<h4>Comments</h4>
<% landmark.comments.forEach((comment) => { %>
<p><%= comment.content %></p>
<small><%= comment.createdBy.username %></small>
<small><%= comment.createdAt.toDateString() %></small>
<% if(locals.isAuthenticated && comment.belongsTo(user)) { %>
<form method="POST" action="/landmarks/<%= landmark.id %>/comments/<%= comment.id %>">
<input type="hidden" name="_method" value="DELETE">
<button class="btn">Delete Comment</button>
</form>
<% } %>
<% }) %>
</section>```
I am unsure why this is happening as I i believe this is correct syntax for the forEach method

Related

JSDOM not loading EJS pages in Node

I tried to load an EJS page using JSDOM however, I can't seem to load the page.
Here's part of my script in app.js:
const { JSDOM } = require("JSDOM");
const dom = new JSDOM('<!DOCTYPE html><p>Hello world</p>');
console.log(dom.window.document.querySelector("p").textContent); // "Hello world"
const list_dom = new JSDOM('views/list.ejs');
console.log(list_dom.window.document);
The first console log is just to make sure that I'm getting JSDOM to work.
Here's the result:
Hello world
Document { location: [Getter/Setter] }
I've tried variations of "views/list", and "views/list.ejs".
Here's my list.ejs:
<%- include('partials/header') -%>
<div class="box" id="heading">
<h1><%=listTitle%></h1>
</div>
<div class="box">
<% newListItems.forEach(function(item){ %>
<form action="/delete" method="post">
<div class="item" contenteditable="true">
<input type="checkbox" name="checkedItem" value="<%=item._id%>" onChange="this.form.submit()">
<p><%=item.name%></p>
</div>
<input type="hidden" name="listName" value="<%=listTitle%>"></input>
</form>
<% }); %>
<form class="item" action="/list" method="post">
<input type="text" name="newItem" placeholder="New Item" pattern="[a-zA-Z][a-zA-Z0-9\s]*" autocomplete="off" required autofocus>
<button type="submit" name="list" value=<%=listTitle%>>+</button>
</form>
</div>
<%- include('partials/footer') -%>

Why is my ejs outputting the actual html code and not rendering it as html?

I am doing some simple validation on a form and using bootstrap for alert dismissing. I have an ejs partial for displaying error messages. When trying to render the error message its just showing the actual block of code.
Here is my partials ejs:
<% if(typeof errors != 'undefined') { %>
<% errors.forEach(error => { %>
<div class="alert alert-warning alert-dismissible fade show" role="alert">
<%= error.msg %>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<% }) %>
<% } %>
Here is where I include that partial to the register.ejs file I have
<%= include ("./partials/messages") %>
<form action="/users/register" method="POST">
<div class="form-group">
<label for="name">Name</label>
<input
type="name"
id="name"
name="name"
class="form-control"
placeholder="Enter Name"
value="<%= typeof name != 'undefined' ? name : '' %>"
/>
Here is a screenshot of what it is outputting:
Why is it showing the actual code instead of rendering as HTML?

getting error in EJS file while running res.render

getting this error:
missing ) after argument list in C:\Users\yoniy\Desktop\YelpCamp\views\campgrounds\index.ejs while compiling ejs
and it's the index.ejs file :
<!-- <%- include "../partials/header" %> -->
<header class="jumbotron">
<div class="container">
<h1><span class="glyphicon glyphicon-tent"></span> Welcome To YelpCamp!</h1>
<p>View campgrounds from all over the world</p>
<p>
<a class="btn btn-primary btn-lg" href="/campgrounds/new">Add New Campground</a>
</p>
<p>
<form action="/campgrounds" method="GET" class="form-inline" id="campground-search">
<div class="form-group">
<input type="text" name="search" placeholder="Campground search..." class="form-control">
</div>
</form>
</p>
</div>
</header>
<div class="row text-center flex-wrap" id="campground-grid">
<%- campgrounds.forEach(function(campground){ %>
<div class="col-md-3 col-sm-6">
<div class="thumbnail">
<img src="<%= campground.image %>">
<div class="caption">
<h4><%= campground.name %></h4>
</div>
<p>
More Info
</p>
</div>
</div>
<%- }); %>
</div>
<!-- <%- include "../partials/footer" %> -->
can't find the syntax error that I get.
thanks for help !
You need to use flow control tags <% for non output parts of your template. In this case the following lines need to be changed:
<%- campgrounds.forEach(function(campground){ %>
Should instead be:
<% campgrounds.forEach(function(campground){ %>
And this line:
<%- }); %>
Should be:
<% }); %>
Update for additional Error
Your formatting for including additional files is incorrect:
<!-- <%- include "../partials/header" %> -->
Should be:
<%- include("../partials/header.ejs") %>
Same for the footer:
<!-- <%- include "../partials/footer" %> -->
Should be:
<%- include("../partials/footer.ejs") %>
Though I cannot validate your paths are correct as I do not know your directory structure.

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!

Why is my JS logic appearing on index (using ejs/express)

im having an issue understanding why my JS is appearing on my layout. Im currently following along with a tutorial on sitepoint creating forms with in express and when i render the layout.ejs + index.ejs with contact as a partial, the logic on partial is appearing on the page as text.
here is the code:
<div class="form-header">
<% if (Object.keys(errors).length === 0) { %>
<h2>Send us a message aa</h2>
<% } else { %>
<h2 class="errors-heading">Oops, please correct the following:</h2>
<ul class="errors-list">
<% Object.values(errors).forEach(error => { %>
<li><%= error.msg %></li>
<% }) %>
</ul>
<% } %>
</div>
<form method="post" action="/contact" novalidate>
<div class="form-field <%= errors.message ? 'form-field-invalid' : ''
%>">
<label for="message">Message</label>
<textarea class="input" id="message" name="message" rows="4"
autofocus><%= data.message %></textarea>
<% if (errors.message) { %>
<div class="error"><%= errors.message.msg %></div>
<% } %>
</div>
<div class="form-field <%= errors.email ? 'form-field-invalid' : '' %>">
<label for="email">Email</label>
<input class="input" id="email" name="email" type="email" value="<%=
data.email %>" />
<% if (errors.email) { %>
<div class="error"><%= errors.email.msg %></div>
<% } %>
</div>
<div class="form-actions">
<button class="btn" type="submit">Send</button>
</div>
</form>

Resources