Mongodb cursor is empty in ejs template(Async call inside ejs ) - node.js

The following router calls the ejs template to populate the values of cursor in to the html page.
router.get('/users_loaded_disconnect', function(req, res) {
res.render('users_loaded_disconnect',
{cursor: req.db.collection('notify_user_state_collection').find({})});
});
user_loaded_disconnect.ejs
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<b> Users Loaded Disconnect </b>
<ul>
<% cursor.nextObject(function(err, item) { %>
<%= JSON.stringify(item) %>
<% }); %>
</ul>
</body>
</html>
The cursor does not work. However if the cursor is iterated within the router like the following code it prints the value
req.db.collection('notify_user_state_collection').find({}).nextObject(function(err, item) {
console.log(JSON.stringify(item));
});
What is wrong in iterating the cursor inside the ejs template ?

The cursor operation is asynchronous. Ejs will not wait for it to complete, and will continue to render the template before data is available. You can't effectively use callbacks inside ejs templates.

Related

SweetAlert2 is not working in node.js

I'm making website for db study.
I wanted to alert to user if user didn't input id and password in register page.
So I installed sweetalert2 by npm. But sweetalert2 doesn't work in route.js which connect user's ask and server.
var swal = require('sweetalert2');
router.post('/register', function(req, res){
if(!req.body.id && !req.body.password){
swal('WARNING','You must input both id and password!','error')
}
else{
swal('COMPLETE','You registered your information!','success');
res.redirect('/');
}
})
How can I fix it?
I used .ejs file to use sweetalert2.
<!DOCTYPE html>
<html>
<head>
<% include ../pages/head %>
</head>
<body>
<% if(fail) { %>
<% include ../partials/alert_login %>
<% } %>
<% include ../pages/login %>
</body>
</html>
in login_connect.ejs includes when user fail login alert_login.ejs file and alert_login.ejs includes script tag of using swal of sweetalert2 module.
But It isn't work. What is the problem?
alert_login.ejs is below.
<script type="text/javascript">
alert("You are not our member!");
</script>

hbs rendered site with handlebars.js in the script - nodejs

I use hbs to render my pages with partials for navigation and footers.
router.get('/test', function (req, res) {
return res.render('test');
});
On one page I have template that uses mustache.js. This template doesn't work as it should as the {{}} seems to be picked up on the hbs render. Below is a basic example that illustrates the error. If I load this as a static page with express I get "Joe is a Web Developer", if I render it with hbs I get "is a".
Are there any work arounds that wont involve me changing how all my pages are rendered?
<!doctype html>
<html lang="en">
<head>
<title>Mustache.js Inline Method</title>
<script type="text/javascript" src="js/libs/mustache.js" ></script>
<script>
var view = {
name : "Joe",
occupation : "Web Developer"
};
function loadtemp(){
var output = Mustache.render("{{name}} is a {{occupation}}", view);
document.getElementById('person').innerHTML = output;
}
</script>
</head>
<body onload="loadtemp()" >
<p id="person"></p>
</body>
</html>
It was simple enough. I just had to escape the brackets with a \
So all it took was
\{{name}}

ejs include on click

I'm trying to create a dynamically included in an ejs page (using <%- include('partials/content') %>) on my node.js project.
Is there a way I can create a variable for the to-be-included page and change it on a button click?
Let's assume your partials/content file includes content like:
<h1>Lorem ipsum dolor sit amet</h1>
A file named partials/content2:
<h1>consectetur adipiscing elit<h1>
Your main template file would wrap the partials content by a <div> with the id result and include a script file where you select this <div> by using var $result = $('#result'); so you have it in a variable. Then you can register a click handler on your button. On click you request the wished template file and replace the content.
Main template:
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
</head>
<body>
<div id="result">
<%- include partials/content.ejs %>
</div>
<button id="change">change</button>
<script>
var $result = $('#result');
$('#change').click(function() {
$result.load('/content2');
});
</script>
</body>
</html>
Then you need a controller on the backend like:
app.get('/content2', function (req, res) {
res.render('partials/content2');
});

How to change something dynamically in the main handlebars skeleton?

I am using handelbars as my templating engine and I am curious to whether I could edit the main handlebars file. What I can do at the moment is something like this:
main.handlebars:
<html>
<head>
</head>
<body>
<div id='headerBox></div>
<div id='contents'>{{{body}}}</div><!--all contents goes here-->
</body>
When I use this method I will could create templates e.g. home.handlebars etc.
But what If I wanted to change something dynamically in the main.handlebars? For example in my website, I would love to have a login form so I would like to have something like this in the main.handelbars:
<html>
<head>
</head>
<body>
<div id='headerBox>{{If logged in print name, if not print sign up}}</div>
<div id='contents'>{{{body}}}</div><!--all contents goes here-->
</body>
</html>
TLDR, how to I change something dynamically in the main handlebars skeleton.
Thanks!
You'll want to write a Handlebars Helper function. Since you didn't include anything about how you're verifying login, I'll write a little demo.
In your template file:
<div id='headerBox'>{{header}}</div>
Handlerbars.registerHelper('header', function() {
if (loggedIn) {
return //however you're getting a username
} else {
return Sign Up
}
});

Node Express EJS Dynamic template render

Hi I am trying to create dynamic template system in express, where I will get dynamic content from database and then render output in single index.ejs file.
Here is my index.js
router.get('/', function(req, res, next) {
var dataFrmDB = {
pageContent: "<%= data.pageTitle %>",
pageTitle: "home"
};
res.render('index', {data:dataFrmDB} );
});
And index.ejs contains:
<%= data.pageContent %>
What I should do so that I can render "home" as output. Is this possible?
I was working on something similar when we migrated from drupal to nodejs, I used ect for rendering instead of jade, its faster and much easier to deal with, However, its much better to use design pattern if you have a big dynamic website
js controller file
model.homepage(function(data)
{
res.render("homepage.ect",data,function(err,html)
{
// Do something before you send the response such as minification, or error handling
res.send(html);
});
});
ECT file
<html xmlns="http://www.w3.org/1999/xhtml" lang="ar" xml:lang="ar">
<head>
<%- #page.title.body %>
<%- #page.headerScript.body %>
<style type="text/css">#homepage-container{min-height:300px;color:#353535;float:right;width:100%}</style>
</head>
<body>
<% include 'upper_bar.ect' %>
<%- #page.headerAd.ads %>
<%- #page.notifications.body %>
<%- #page.autocomplete.body %>
<%- #page.redirect.body %>
<%- #page.navigation.body %>
<%- #page.overlayAd.ads %>
</body>
</html>
why bother so much?
You can easily do this using templatesjs
without any template engine.
let me show you how your work can be done using templatesjs
html file
<html>
<head>
<title> <%title%> </title>
</head>
<body>
your content goes here
</body>
</html>
now use templatesjs in you node.js file
var tjs = require("templatsjs");
router.get('/', function(req, res, next) {
var data = fs.readFileSync("./index.html");
tjs.set(data); // invoke templatesjs
var output = tjs.render("title","home");
/* this will replace the <%title%> tag
in the html page with actual title*/
res.write(output);
res.end()
});
i have used fs.readFileSync to keep simplicity of code you can use the asynchronus function if you want (fs.readFile).
a good referrence can be found here
Installation :
$ npm install templatesjs

Resources