EJS unexpected Token "else" - node.js

I have a problem with syntax in ejs which isn't obvious to me:
<form class="dataForm" action="<%= template.actionPath %>" method="post">
<% for(var i in template.inputVar) { %>
<label><%= template.inputVar[i].labelName %></label>
<br>
<% if (template.inputVar[i].type == "option") { %>
<select name="<%= template.inputVar[i].name %>">
for(var j in template.inputVar[i].options) { %>
<option value="<%= template.inputVar[i].options[j] %>"><%= template.inputVar[i].options[j] %></option>
<% } %>
</select>
<% } else { %>
<input type="<%= template.inputVar[i].type %>" name="<%= template.inputVar[i].name %>">
<% } %>
<br><br>
<% } %>
I am rendering a webpage where a form is created. Now I want to add a feature that allowes me to have selections in my form.
Unfortunately ejs does not like my the "else" it says:
SyntaxError: Unexpected token else in C:\Users\etc... while compiling ejs
I did some research about this issue but I could not find something that might help me.

Your for line is missing the opening ejs script tag
for(var j in template.inputVar[i].options) { %>
to
<% for(var j in template.inputVar[i].options) { %>
Also, you should close your form tag

Related

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!

ejs for loop randering

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>

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) { %>

Passing an array to a EJS view, using Bookshelf.JS

My logic:
/* GET /events/list */
router.get('/events/list', function(req, res) {
new db.Tag({})
.fetchAll()
.then(function(tags) {
res.locals.title = "List of events";
res.locals.tags = tags;
res.render('events/list.ejs');
});
});
My view:
<% for (var tag in tags) { %>
<div class="checkbox">
<label>
<input type="checkbox" data-tag-id="<%= tag.tagId %>" />
<%= tag.name %>
</label>
</div>
<% } %>
What I'm getting:
[x] undefined
[x] undefined
[x] undefined
[x] undefined
What I should be getting:
[x] foo
[x] bar
[x] zort
[x] troz
I also tried passing
res.locals.tags = tags.toJSON();
and also
res.locals.tags = JSON.stringify(tags);
So.. how do I finally pass my collection to an EJS view?
I also logged (console.log(tags)) just after then(function(tags) and I'm getting the models (tags in this case) correctly.
I also tried tags.forEach in my EJS view but a native javascript array like this: [{tagId:1, name:"blah"}, {tagId:2, name"Foo"}] doesn't have "forEach" method implemented
In your template, use forEach (if available) or loop using the index instead.
server.js
res.locals.tags = tags.toJSON();
view.html (with [].forEach)
<% tags.forEach(function(tag) { %>
<div class="checkbox">
<label>
<input type="checkbox" data-tag-id="<%= tag.tagId %>" />
<%= tag.name %>
</label>
</div>
<% }) %>
view.html (with indices)
<% for (var i in tags) { %>
<div class="checkbox">
<label>
<input type="checkbox" data-tag-id="<%= tags[i].tagId %>" />
<%= tags[i].name %>
</label>
</div>
<% } %>
Here's an alternative to using Array.prototype.forEach. You give the Bookshelf collection to the view. Bookshelf.Collection has its own .forEach:
server.js
res.locals.tags = tags; // NOT .toJSON()
view.html
<% tags.forEach(function(tag) { %>
<div class="checkbox">
<label>
<input type="checkbox" data-tag-id="<%= tag.id %>" />
<%= tag.get('name') %>
</label>
</div>
<% }) %>

How do I create a dynamic dropdown menu in NodeJS?

Am experimenting with node Js. How do you create a dynamic dropdown menu?
Thanks.
<div class="control-group">
<%- form.label("state_or_province", false, {class: "control-label"}) %>
<div class="controls">
<!-- <%- form.input("state_or_province") %> -->
<select id="Facility_state_or_province" name="Facility[state_or_province]" size="1">
<% state_or_province_list.forEach(function (state_or_province_entry) { %>
<option value = "<%= state_or_province_entry.lookup_code %>" <%= (facility.state_or_province != null) && (facility.state_or_province == state_or_province_entry.lookup_code) ? 'selected = "selected"' : '' %>><%= state_or_province_entry.meaning %></option>
<% }); %>
</select>
</div>
</div>

Resources