Storing Express data in global variable through view - node.js

I have a data object "bootstrappedUser" being passed into the view through a route.
app.get('/', function(req, res) {
res.render('index.ejs',{
bootstrappedUser: req.user,
page: 'rest'
});
});
I'd like to store the "bootstrappedUser" JSON object into a global variable and use that variable to keep persistent login. Currently the window.bootstrappedUserObject is being accessed when bootstrappedUser is defined but it is not being set to anything.
<% if (bootstrappedUser!= undefined) { %>
<script>
window.bootstrappedUserObject = <% bootstrappedUser %>
</script>
<% } %>
I am receiving the following source code on login
<script>
window.bootstrappedUserObject =
</script>

You want to use <%= %> instead of <% %>:
<% if (bootstrappedUser!= undefined) { %>
<script>
window.bootstrappedUserObject = <%= bootstrappedUser %>
</script>
<% } %>
<% %> just evaluates JavaScript whereas <%= %> interpolates the result of an expression into your template.

Related

Express nodejs Handlebars not rendering database content correctly inside EJS file

Im having a problem with my express nodejs project where the handlebars wont render on my ejs file. I created some handlebars which fetch some data from a database. When I render the hbs files the content from the database is displayed correctly, but when I include the hbs files in my ejs file together with my page header and footer the content from the database is not retrieved. I would appreciate any help.
cars.hbs
<!DOCTYPE html>
<html>
<body>
<p> The {{dbcars.model}} features a {{dbcars.specs.engine}} engine... </p>
</body>
</html>
home.ejs
<body>
<p> <%- include('navbar.ejs') %> </p>
<p> <%- include('handlebars/cars.hbs') %> </p>
<p> <%- include('footer.ejs') %> </p>
</body>
</html>
(note: when I render (handlebars/cars.hbs) instead of (home.ejs) the handlebars render correctly. )
car.js
router.get('/vehicle/:id', async (req, res) => {
Car.findById(req.params.id, function(err, carRouter) {
res.render("home.ejs", {
dbcar: carRouter
})
This is the result im getting:
(navbar)
The {{dbcars.model}} features a {{dbcars.specs.engine}} engine...
(footer)
This is the result im trying to get:
(navbar)
The Nissan Sentra features a 2.0 L 4-cylinder engine...
(footer)
You should create cars.ejs as well
cars.ejs
<% if (dbcar.length > 0) { %>
<% dbcar.forEach(dbcars => { %>
<p> The <%= dbcars.model %> features a <%= dbcars.specs.engine %> engine... </p>
<% }) %>
<% } else { %>
<p>There is no information to display.</p>
<% } %>
home.ejs
<%- include('handlebars/cars.ejs'); %>
car.js
router.get('/vehicle/:id', async (req, res) => {
Car.findById(req.params.id, function(err, carRouter) {
res.render("cars.ejs", {
dbcar: carRouter
})
};
};

Unable to send user data to views

This is my general format for views:
<html>
<head></head>
<body>
<%- include('_header'); %>
<main>
(html code for a particular page)
</main>
<%- include('_footer'); %>
</body>
</html>
This is my code for _header.ejs:
<header>
<a id="logos" href="/">
<img id="dr" src="/imgs/logo.png" alt="logo">
</a>
<div id="nav_bar">
Achievements
Sponsors
Team
Gallery
<% if(profile_user.id) { %>
Profile
<% } else { %>
Log In
<% } %>
</div>
</header>
I have routes folder which gets controllers from different controllers. I am getting an error _header.ejs that profile_user.id is not defined.
11| Gallery
>> 12| <% if(profile_user) { %>
13| <%= profile_user.user %>
14| <% } else { %>
15| Log In
profile_user is not defined
Now the solution to this problem would be to use User.findOne() but then I don't want to do this for all controllers. I want to globalize profile_user into all views. Can you tell me how to do that?
Also, I have tried to do this by adding middleware and sending using it in my app.js but it never gets called.
console.log(10);
if (await req.isAuthenticated()) {
// req.user contains the current signed in user from the session cookie and we are just sending this to the locals for the views
res.locals.user = req.user;
console.log('Locals\' user loaded');
}
next();
}
In app.js I have called the function
app.use(passport.setAuthenticatedUser);
and updated the _header.ejs code to this:
<%= user.user %>
<% } else { %>
Log In
<% } %>
Solution to any of the two problems (through middleware or through controllers) will do.
Let me know if you need anything else

a property is not defined ejs: nodejs

I was following a tutorial and got stuck here. Everything looks ok to me. Still I am getting this error. Can some one point me to the right direction.
memberName is not defined
<% for(var i=0; i < notes.length; i++) { %>
<div class="list-group-item">
<div>Note from <em><strong><%=memberName[i]%></strong></em> on:
<%= createdOn.toDateString() %>
<strong><%= project[i] %></strong></div>
<div><strong>Work yesterday:</strong>
<%= workYesterday[i] %>
</div>
<div><strong>Work today:</strong>
<%= workToday[i] %>
</div>
<div><strong>Impediment:</strong>
<%= impediment[i] %>
</div>
</div>
<%}%>
Controller code:
exports.list = function (req, res) {
var query = Standup.find();
query.limit(12)
.exec(function (err, results) {
console.log(results);
res.render('index', { title: 'Standup - List', notes: results });
});
};
<%=memberName[i]%> in the ejs file mean "when I ll send the ejs, I ll replace that by the value of memberName".
But in your controller, you don t provide it, which block ejs.
In the controller, you should have something like:
res.render('index', {
title: 'Standup - List',
notes: results,
memberName: memberName //<--
});
When this one will be fixed, you ll also have to provide createdOn, project, workYesterday, workToday, workTomorrow and impediment.
<%= is a EJS tag for evaluating values in HTML.
<%= memberName %> will output the value of variable memberName in your HTML code. Thus you need to pass the parameter memberName while you are rendering the html page. You have missed out the parameter.
Your controller code should look like:
exports.list = function (req, res) {
var query = Standup.find();
query.limit(12)
.exec(function (err, results) {
console.log(results);
res.render('index', { title: 'Standup - List', notes: results, memberName: 'Test Member Name' });
});
};
You're probably looking for this:
<% for(var i=0; i < notes.length; i++) { %>
<div class="list-group-item">
<div>Note from <em><strong><%= notes[i].memberName %></strong></em> on:
<%= notes[i].createdOn.toDateString() %>
<strong><%= notes[i].project %></strong></div>
<div><strong>Work yesterday:</strong>
<%= notes[i].workYesterday %>
</div>
<div><strong>Work today:</strong>
<%= notes[i].workToday %>
</div>
<div><strong>Impediment:</strong>
<%= notes[i].impediment %>
</div>
</div>
<%}%>
Which can be further reduced to this:
<% notes.forEach(function(note) { %>
<div class="list-group-item">
<div>Note from <em><strong><%= note.memberName %></strong></em> on:
<%= note.createdOn.toDateString() %>
<strong><%= note.project %></strong></div>
<div><strong>Work yesterday:</strong>
<%= note.workYesterday %>
</div>
<div><strong>Work today:</strong>
<%= note.workToday %>
</div>
<div><strong>Impediment:</strong>
<%= note.impediment %>
</div>
</div>
<% }) %>

CAN we do something like <% alert("TEMP") %> in EJS

I have sent a variable in node.js from res.render() function and I have to use that variable for my script in EJS templating for DOM manipulation.
From Node.js:
res.render('index', {TEMP: 'xyz'});
In the HTML:
<p>This is a HTML demo</p>
<div>
I'm the TEMP variable: <%= TEMP %> <!-- this is going to output xyz -->
<script>
var getTemp = <%= TEMP %>;
console.log(getTemp);
</script>
</div>

How to array of objects in template ejs?

I have a results variable that is an array of objects. I carry the results variable from my javascript file to my main route file. I am trying to render my page to display lists of each object in my template ejs file. I am able to list everything fine, but the lists are coming out as [object object] instead of the actual words that are in the objects. How do I get this to display as strings in my template file?
This is my route file:
app.get('/announcement', function(req,res){
var getAnnouncements = require('../public/javascripts/announcement.js'); //Load the module, get the name of the script file
//define the functions here
var onSpreadsheetSuccess = function (results) { //result is announcementArray
//add results list to template);
res.render('announcement', {title: "Announcement page", results: results});
}
getAnnouncements.loadSheet(onSpreadsheetError, onSpreadsheetSuccess); //call the function from script with the parameters passed
})
This is what I am doing in my template ejs file:
<ul>
<% results.forEach(function(result){ %>
<li><%= result %></li>
<% }); %>
</ul>
<ul>
<% for(var i=0; i<results.length; i++) { %>
<li>
<%= results[i] %>
</li>
<% } %>
</ul>
This will show list of id of your results, just change _id by your property of objects as you want to show.
<ul>
<% results.map((result)=>{ %>
<li>
<%= result._id %>
</li>
<% }) %>
</ul>
My answer is as follows. I changed one line from the answer by other person.
<ul>
<%for (var result in results){%>
<li><%=result%>:<%=results[result]%></li>
<%}%>
</ul>
With modern JS it can be simplified to
<ul>
<% for (var result of results) { %>
<li>
<%= result %>
</li>
<% } %>
</ul>
You should be fine with this:
<ul>
<% for(let i = 0; i < results.length; i++){ %>
<li><%= results[i].title %></li>
<% } %>
</ul
or when you rather like to use the forEach:
<ul>
<% results.forEach( function (result) { %>
<li><%= result.title %></li>
<% }) %>
</ul
the object you push(ed) into your array:
const result = {
title: anyTitle,
input: anyInput
}
Try this:
<ul>
<%for (var result in results){%>
<li><%=result%></li>
<%}%>
</ul>

Resources