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
Related
I want to load a default header on a .ejs file.
I asked ChatGPT but it didnt give me the correct code.
This is the index.ejs file that is being send over email:
<!DOCTYPE html>
<html>
<head>
<title>My Web Page</title>
</head>
<body>
<% include header %>
<h1>Welcome to My Web Page</h1>
</body>
</html>
ChatGPT said to use the tag <% include header %> but that didnt work.
These two fields are in the same folder.
The header.html file is the following:
<header>
<nav>
<ul>
<li>Home</li>
<li>About</li>
<li>Contact</li>
</ul>
</nav>
</header>
Is there any way to render html inside a .ejs file?
Below is the actual code that sends the email:
async function sendEmails(winningCampaigns) {
fs.readFile('backend/views/index.ejs', 'utf-8', async (err, data) => {
if (err) throw err;
let html = data.replace(/{{name}}/g, 'John Doe');
for (let campaign of winningCampaigns) {
sendEmail({
to: "jcasasmail#gmail.com",
subject: "Hello ✔", // Subject line
html: html
})
}
});
}
For starters, there's no purpose for the async keyword if the function doesn't use await. Any code that awaits sendEmails won't actually wait for readFile to resolve because it's callback rather than promise-based. Consider using fs.promises.readFile here, or better yet, use EJS's built-in renderFile.
On to the main point, your code doesn't run EJS at all. fs.readFile doesn't treat the file as a template, even with an .ejs extension.
data.replace(/{{name}}/g, 'John Doe'); defeats the purpose of EJS, which should be doing the templating. You're probably in a testing phase, but name isn't used in the template.
You can use <%- include("header.html") %> in EJS to include a .html file, which should be in the same directory as the EJS template.
Here's how I'd approach the sendEmails function:
const ejs = require("ejs"); // ^3.1.8
const path = require("path");
async function sendEmails(winningCampaigns) {
const p = path.join("backend", "views", "index.ejs");
const html = await ejs.renderFile(p, {name: "John Doe"});
for (const campaign of winningCampaigns) {
sendEmail({
to: "<Your email address>",
subject: "Hello ✔",
html,
});
}
}
Note that I'm using path.join() rather than string concatenation to build system-agnostic paths.
If sendEmail is async, be sure to await that as well.
My file structure is:
├── backend
│ └── views
│ ├── header.html
│ └── index.ejs
└── send-emails.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>
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.
i'm using html files instead of ejs, but the express engine is ejs
views
|
|--header.html
|--footer.html
|
|--index.html
I configured like
app.set('views', __dirname + '/views');
app.engine('html', require('ejs').renderFile);
I render my index template by this:
res.render('index.html', {title: 'test'});
But how can i include header and footer.html in index.html
Similar posts
Node.js express: confuse about ejs template
Existing example which is not working
https://github.com/visionmedia/express/tree/master/examples/ejs
The original method for what you asked would be to use partials. Partials have since been removed, and replaced with the include function of EJS. This is how you would include a file:
<% include header.html %>
<% include footer.html %>
Any locals you pass to the rendered page will also be passed to an include. For example:
app.js
app.get('/', function(req, res) {
res.render(__dirname + '/index.html', {
string: 'random_value',
other: 'value'
});
});
index.html
<!DOCTYPE html>
<body>
<%= other %>
<% include content.html %>
</body>
content.html
<pre><%= string %></pre>
The resultant HTML you would get is:
<!DOCTYPE html>
<body>
value
<pre>random_value</pre>
</body>
i'm using the EJS template engine with nodejs/express and i'm wondering if it's possible to add another css or js file in e.g the index.ejs (not the layout.ejs)
layout.ejs
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
<link rel='stylesheet' href='/stylesheets/smoothness/jquery-ui-1.8.14.custom.css' />
</head>
<body>
<%- body %>
</body>
</html>
index.ejs
<h1><%= title %></h1>
<p>Welcome to <%= title %></p>
i don't want to add the second css file in every template but only the index.ejs - is there any way i can do that?
found a solution here: Node.js with Express: Importing client-side javascript using script tags in Jade views?
it's using jade instead of EJS but works all the same.
here are some code-snippets for express 2.4.0.
you have to add the following "helpers" to your app.js
app.helpers({
renderScriptsTags: function (all) {
if (all != undefined) {
return all.map(function(script) {
return '<script src="/javascripts/' + script + '"></script>';
}).join('\n ');
}
else {
return '';
}
}
});
app.dynamicHelpers({
scripts: function(req, res) {
return ['jquery-1.5.1.min.js'];
}
});
the layout.ejs looks sth like this:
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
<%- renderScriptsTags(scripts) %>
</head>
<body>
<%- body %>
</body>
</html>
if you don't add any scripts to the scripts-array, only 'jquery-1.5.1.min.js' will be included - if you want to add files to a subpage you can do this like so:
test.ejs
<% scripts.push('jquery-ui-1.8.14.custom.min.js', 'jquery.validate.min.js') %>
<h1><%= title %></h1>
<p>I'm a template with 3 js files in the header</p>
that's it.
As helpers and dynamicHelpers are gone in Express > 3, I rewrote pkyeck code so it works in Express 3.
So in app.js have this instead of the helpers / dynamicHelpers. Leave everything else as is.
app.locals({
scripts: [],
renderScriptsTags: function (all) {
app.locals.scripts = [];
if (all != undefined) {
return all.map(function(script) {
return '<script src="/javascripts/' + script + '"></script>';
}).join('\n ');
}
else {
return '';
}
},
getScripts: function(req, res) {
return scripts;
}
});
In app.js add line:
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(express.static(__dirname + '/public')); // This line.
In layout.ejs:
<!DOCTYPE html>
<html>
<head>
<title>Authentication Example</title>
<link rel="stylesheet" href="/stylesheets/style.css"/>
<script src="/javascripts/jquery.js"></script>
</head>
<body>
<%- body %>
</body>
</html>
In index.ejs or login.ejs:
<h1>Login</h1>
<form method="post" action="/login">
<p>
<label>Username:</label>
<input type="text" name="username">
</p>
<p>
<label>Password:</label>
<input type="text" name="password">
</p>
<p>
<input type="submit" value="Login">
</p>
</form>
<script src="/javascripts/test.js"></script> <!-- Second Script -->
In test.js:
$(document).ready(function() {
try{
alert("Hi!!!");
}catch(e)
{
alert("Error");
}
});
Regards.
Thanks #asprotte for providing this for express 4.x. Did you tested this?
Because it does not appears to be working for me. So I have made some changes to your code here are they:
Put this in app.js file
app.locals.scripts = [];
app.locals.addScripts=function (all) {
app.locals.scripts = [];
if (all != undefined) {
app.locals.scripts = all.map(function(script) {
console.log(script);
return "<script src='/js/" + script + "'></script>";
}).join('\n ');
}
};
app.locals.getScripts = function(req, res) {
return app.locals.scripts;
};
then in template file put (I am using ejs template here) :
<% addScripts(['cart.js']) %>
Then in the layout file we need these to append at the bottom of the page get the scripts
<%- getScripts() %>
I have tested it and its working for me. Please correct me if I am wrong.
Thanks,
Thanks for illustrating this option pkyeck!
In express 4.x app.locals is an object. Here's pkyeck's answer rewritten to work in express 4.x:
app.locals.scripts = [];
app.locals.addScripts=function (all) {
app.locals.scripts = [];
if (all != undefined) {
return all.map(function(script) {
return "<script src='/javascripts/" + script + "'></script>";
}).join('\n ');
}
else {
return '';
}
};
app.locals.getScripts = function(req, res) {
return scripts;
};