Ejs engine with html not working - node.js

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>

Related

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

How to render multiple views using Node+Express

I have a header.html and a footer.html which I would like to be rendered along with other views. I want to accomplish this using Node+Express.
I tried to render views in the following way but clearly it doesn't work:
var express = require('express');
var app = express();
app.get('/', function(req, res) {
res.render('header');
res.render('home');
res.render('footer');
});
You have to set a template engine to your project.
You can use Swig for instance, it works very nice and it is well documented.
The example below, shows you how to set it and how you can call partial views from a layout or master page.
Install it by doing npm install swig --save on your project root.
You need to install an additional library called consolidate which acts as interface among different template engine libraries, it is kind of standard in express applications.
npm install consolidate --save
require the library in your main script with
consolidate = require('consolidate');
swig = require('swig');
Configure it as follows:
app.engine('html', cons.swig);
app.set('view engine', 'html');
app.set('views', __dirname + '/views'); // set your view path correctly here
Then you can render a page as:
app.get('/', function (req, res) {
res.render('index', {});
});
(Example taken from Swig's author, Paul Armstrong github page)
Layout.html:
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>{% block title %}{% endblock %} - Example</title>
</head>
<body>
<header>
<h1>{% block title %}{% endblock %}</h1>
{% block header %}{% endblock %}
<nav>
<ul>
<li>Home Page</li>
<li>People</li>
</ul>
</nav>
</header>
<section role="main">
{% block body %}{% endblock %}
</section>
</body>
</html>
Index.html:
{% extends 'layout.html' %}
{% block title %}Home Page{% endblock %}
This way, you can decoupled your views as you need :)
When you are using pug, you can take an advantage of include feature, like #Kangcor suggestion
home.pug
html
head
include ./path/to/header.pug
title= title
body
...
include ./path/to/footer.pug
You can use Handlebars partial views
Here is a well documented library
https://handlebarsjs.com/guide/partials.html#basic-partials
Install hbs
https://handlebarsjs.com/installation/#npm-or-yarn-recommended
npm install handlebars
Configure Handlebars
// import library on the your start js file ie: app.js || index.js
let hbs = require('hbs');
// view engine setup
app.set('views', path.join(__dirname, 'views'));
hbs.registerPartials(__dirname + '/views/partials');
app.set('view engine', 'hbs');
Create your partial views ie: header.hbs and footer.hbs on the partials directory
Create a file layout.hbs and you can call the partial view as follows
<div>
{{> header}}
{{> body}}
{{> footer}}
</div>
Then when calling
res.render("home", {});
home.hbs will be mapped as the body and the footer and header will be added to the layout.

Nodejs Include Other Views?

I am using html views.
Is there a something like this? :
{{include head.html}}
index
</body>
</html>
What you are looking for is a templating engine, since you mentioned the {{ }}tags I am assuming you are using Hogan.js aka moustache(the javascript version).
The documentation can be found here and what you are specifically looking for is the partials section.
Please note, the default express app(if you select hogan) comes installed with the hjs module which does not support partials, you will need to install the hogan-express module and replace them.
A partial looks like so:
{{> head}}
index
</body>
</html>
Partials are sent from a get or post object like so:
res.render('index.html', {
partials: {
head: 'partials/head.html'
}
});
You are looking for a template engine for nodejs?
For example check here: http://node-modules.com/search?q=template+engine
I found the solution.
server.js
var hbs = require('hbs');
app.set('view engine', 'html');
app.engine('html', hbs.__express);
app.set('views', __dirname + '/views');
app.use(express.static(__dirname + '/public'));
hbs.registerPartials(__dirname + '/views/'); <-------- include folder
index.html
Index.html includes head.html like this:
{{> head}}
index
</body>
</html>
If you do not want to use ejs or jade etc then you could do it with jquery. Put this code in index.html
<html>
<head>
<title></title>
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script>
$(function(){
$("#header").load("header.html");
$("#footer").load("footer.html");
});
</script>
</head>
<body>
<div id="header"></div>
<!--Remaining section-->
<div id="footer"></div>
</body>
</html>

nodejs ejs include unexpected identfier

i'm using nodejs + express + ejs and i am having a problem when i try to include another view.
When I try:
<% include dochead %>
I get 'unexpected identifier';
when i try:
<% include /admin/global/dochead %>
I get 'include is not defined';
What is going on?
Thanks
Try
<%- include ('dochead') %>
or
<%- include ('admin/global/dochead') %>
set
app.set('view engine', 'ejs');
app.set('views', 'YOUR CUSTOM VIEW FOLDER PATH FROM ROOT FILE');
I think here <% include /admin/global/dochead %> should be
<% include ../admin/global/dochead %>
or
<% include admin/global/dochead %>
depending on the location.
Also check the view engine you use
app.set('view engine', 'ejs');

is there a way to add CSS/JS later using EJS with nodejs/express

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;
};

Resources