Include HTML blocks Using node.js - node.js

This is what I want but probably can't have:
Using node.js and express and maybe ejs, I would like to, while writing a regular HTML file in my client dir, server-side-include a template block of HTML. It would be cool also if I could pass variables into the include from the HTML document.
Sooo something like:
<!doctype html>
<html>
<head>
<%include head, ({title: "Main Page"}) %>
</head>
<body>
<% include header, ({pageName: "Home", color: "red"}) %>
...
<<% include footer%>>
</body>
</html>
Is there anyhting in node world that works like this? Or any thing that comes close and that could be maybe adapted for this functionality? I would not use it exactly in the way indicated here, but this is the functionality that I am looking for.
I have looked into jade, handlebars, ember and ejs, and ejs seems to come the closest. Maybe one of these does this already, but I am just confused about the implementation.
Any suggestions would be great!

OK I got it...
server.js
var express = require('express');
var server = express();
var ejs = require('ejs');
ejs.open = '{{';
ejs.close = '}}';
var oneDay = 86400000;
server.use(express.compress());
server.configure(function(){
server.set("view options", {layout: false});
server.engine('html', require('ejs').renderFile);
server.use(server.router);
server.set('view engine', 'html');
server.set('views', __dirname + "/www");
});
server.all("*", function(req, res, next) {
var request = req.params[0];
if((request.substr(0, 1) === "/")&&(request.substr(request.length - 4) === "html")) {
request = request.substr(1);
res.render(request);
} else {
next();
}
});
server.use(express.static(__dirname + '/www', { maxAge: oneDay }));
server.listen(process.env.PORT || 8080);
and in /www I have the following .html files:
index.html
{{include head.html}}
{{include header.html}}
<p class="well">Hello world!</p>
{{include footer.html}}
head.html
<!DOCTYPE html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
{{include include.css.html}}
<script src="js/vendor/modernizr-2.6.2.min.js"></script>
</head>
<body>
include_css.html
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/bootstrap.css">
<link rel="stylesheet" href="css/bootstrap-responsive.css">
<link rel="stylesheet" href="css/main.css">
header.html
<div class="well">
<h1>HEADER</h1>
</div>
footer.html
<div class="well">
<h1>FOOTER</h1>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/vendor/jquery-1.9.1.min.js"><\/script>')</script>
<script src="js/plugins.js"></script>
<script src="js/bootstrap.min.js"></script>
<script src="js/main.js"></script>
<!-- Google Analytics: change UA-XXXXX-X to be your site's ID. -->
<script>
var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
g.src='//www.google-analytics.com/ga.js';
s.parentNode.insertBefore(g,s)}(document,'script'));
</script>
</body>
</html>
It all comes through, even includes in includes and static content. It is all performed on html files, and in a context that feel like vanilla web authoring.
++++Oops+++++
Well I almost all of it. I forgot that I also wanted to be able to pass variables into the include from the templates. I haven't tried that yet... any ideas?
++++Update+++++
Ok I figured it out.
This discussion made it clear, i guess i just didn't know enough about how ejs worked.
I have changed index.html to begin with variable declarations:
{{
var pageTitle = 'Project Page';
var projectName = 'Project Title';
}}
and then you can call these variables from within the includes, no matter how deeply they are nested.
So for instance, index.html includes start.html which includes header.html. Within header .html I can call {{= projectName}} within the header even though it was declared inside index.html.
I have put the whole thing on github.

I would recommend nunjucks or pejs. Nunjucks is jinja-inspired, while pejs is just ejs + inheritance, block, and file support.
pejs has some issues with space chomping at the moment, but it's still pretty useful. Of the two, I prefer the separation layer that comes with nunjucks.
Jade is pretty cool and has the feature-set you're looking for, but it has a very unique syntax. References for jade: template inheritance, blocks, includes

Jade does allow server side includes of HTML blocks and any locals scoped variable will get passed to the included jade template. But the both files must be in jade syntax format not raw HTML if you want to do this.
Any variable you would like to pass can just be added to the locals object.

var express = require('express');
var app = express();
var path = require('path');
app.get("/" ,(req,res) => {
res.sendFile(path.join(__dirname+'../../templates/index.html'));
});
app.use(express.static(path.join(__dirname+'../../templates/public')));
This way you can call HTML where ever the folder that contains HTML.
if you want to include CSS and Javascript use express.static see the last
line of code

Related

Express js app.use() not working properly?

Alright guys, I've been following the fcc node js tutorial for beginners. I have trouble getting the use() function from the express framework to work. I followed all the steps (I've copied exactly what he's doing), but when I open the Chrome/Firefox debug console my I can see my folders are not swapped for the alias I've set (is 'static' instead of 'public'). For anyone wondering, I'm stuck on this part -> https://youtu.be/-FV-moMWRSA?t=230.
my code:
const path = require('path');
const express = require('express');
const app = express(); //this function returns an object with many functions
app.use('/public', express.static(path.join(__dirname, 'static')));
app.get('/',
(req, res) => {
res.sendFile(path.join(__dirname, 'static', 'index.html'));
});
app.listen(3000);
my html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="/static/css/main.css">
<script src="/static/js/main.js"></script>
</head>
<body>
<p>Test paragraph</p>
</body>
</html>
anyone know what's going on?
You have wrong paths in your html. Since you're using /public in your middleware, only requests with /public will be looked in the static folder to see if a filewith the requested name exists or not.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="/public/css/main.css">
<script src="/public/js/main.js"></script>
</head>
<body>
<p>Test paragraph</p>
</body>
</html>
Hope this helps !

Adding CSS File to ejs tempelate using variable from server side

I am trying to add css file dynamically in ejs tempelate.
I know how to include ejs file but not getting how to add css file dynamically.
Code :-
Index.js
router.get('/', function(req, res, next) {
res.render('template', { title: 'abc',page:'index',cssa:'home'});
});
template.ejs
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="/stylesheets/style.css">
<!-- Here I want to add home.css file -->
</head>
<body>
<!-- including my ejs file -->
<%- include(page) %>
</body>
</html>
I tried :
<link rel="stylesheet" type="text/css" href="/stylesheets/\<%= cssa %>\" >
<% include %><%= cssa %><% .css %>
Goal:
to pass the server side received variable(cssa) in stylesheet source.
Don't need to concat the css path and variable, you can also do it as follows:
<link rel='stylesheet' href='/stylesheets/<%= yourVariableName %>.css' />
Method to include :
<% var css_link = '/stylesheets/' + cssa + '.css'; %>
<link rel="stylesheet" type="text/css" href="<%= css_link %>" >
Credit goes to #SpiRT
Alternatively :
<link rel="stylesheet" type="text/css" href="/stylesheets/<%=cssa%>.css">
I've found it most convenient to inject custom css scripts through an array which can then be processed in the ejs template.
This method would allow you to render any amount of CSS files that are additionally required (example, you have a site that uses 1 standard css across all pages but have 1 or 2 page specific ones which can then be included in the model passed through the ejs renderer to that specific page/route).
In the example it's a given that the css files are in the same folder, however that can be changed to each one's liking:
router side:
router.get( ... {
model = {};
model.Stylesheets = [];
model.Stylesheets.push("stylefile");
res.render("view",{model:model});
});
with the custom stylesheets being pushed though to the view, then the ejs files can be something like:
<%
var customStylesheets = "";
model.Stylesheets.forEach(function(style){
customStylesheets+='<link type="text/css" rel="stylesheet" href="css/'+style+'.css">';
})
%>
<!DOCTYPE html>
<html>
<head>
<title><%= model.title %></title>
<link type="text/css" rel="stylesheet" href="css/standard.css">
<%- customStylesheets %>
...
</head>

why my css not finding?

I have attached my css file to my html file. And then i run and open page using express in node js. However, the css file does not open when i run the webserver through node js.
html(show.ejs)
<html>
<head>
<link rel="stylesheet" type="text/css" href="assets/css/style.css" media="screen" />
</head>
<body>
<h1> Value is <%= detail %></h1>
</body>
</html>
node js
//required npm
var express = require('express');//express 4.*
var path = require('path');
// define app
var app = express();
// set up template engine
app.set('view engine', 'ejs');
//static files
//app.use('/static', express.static('/public')); //not working
app.use('', express.static(path.join(__dirname, 'public'))); //not working
//app.use(express.static(__dirname + '/public')); //not working
//app.use('/public/assets', express.static('public/assets')); //not working
app.get('/show/:id', function (req, res) {
res.render('./panel/show', {
detail: req.params.id ,
});
//port
app.listen(3000);
my project folder
node_modules
views
panel
show.ejs
public
assets
css
style.css
app.js
package.json
By entering <link rel="stylesheet" type="text/css" href="assets/css/style.css" media="screen" /> You are trying to find the assets folder in your out of public directory.
So, when you / it will find public directory which is statically defined in express server.
<html>
<head>
<link type="text/css" href="/assets/css/styles.css" rel="stylesheet">
</head>
<body>
<h1> Value is <%= detail %></h1>
</body>
</html>

Files inside the assets folder are not being loaded in sub pages

I have a folder structure like below
assets
bootstrap
css
style.css
js
jquery.min.js
views
partials
head.ejs
header.ejs
scripts.ejs
home.ejs
user_registration.ejs
In my app.js file I have set this assets folder like:
var app = express();
app.use('/static', express.static('assets'));
var routes = require('./routes/routes');
In my routes.js file
exports.userLogin = function(req, res){
var userLogin = req.params.userId;
var users = memberData.users;
res.render('user_registration', {
title : 'Welcome',
users : users
});
};
In my head.ejs file
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="static/bootstrap/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
<link href='https://fonts.googleapis.com/css?family=Montserrat:400,700' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
<link rel="stylesheet" href="static/css/style.css" type="text/css">
Now inside in user_registration file, I have following code
<!DOCTYPE html>
<html lang="en">
<head>
<% include partials/head.ejs %>
</head>
<body>
<% include partials/scripts.ejs %>
</body>
</html>
By using this my jQuery, bootstrap files that are inside assets folder are not being loaded. But the home.ejs page is working normally.
When I check at the console, the home.ejs page is taking those files in following format
http://localhost:3000/static/bootstrap/css/bootstrap.min.css
whereas user_registration page is taking following format
http://localhost:3000/user_registration/static/bootstrap/css/bootstrap.min.css
I am very new in express.js framework, so I could not figure out how to solve this problem. Can anybody please help me. Thank you.
Problem is here app.use('/static', express.static('assets')); in your code line.
Replace it with
app.use(express.static(path.join(__dirname, 'assets')));
And in your head.ejs file replace bootstrap css calling line
href="static/bootstrap/css/bootstrap.min.css" to href="/bootstrap/css/bootstrap.min.css"
Hop you understand.
The problem is: the href link to static resource should be absolute, not relative. Specifically, in head.ejs it should be:
href="/static/bootstrap/css/bootstrap.min.css"
...
href="/static/css/style.css"
NOT:
href="static/bootstrap/css/bootstrap.min.css"
...
href="static/css/style.css"
As app.use('/static', express.static('assets')); stated, the static assets are hosted under /static namespace (absolute URL starting with /static), it doesn't make any sense to use relative URL any more.

ejs 'partial is not defined'

Okay I have a mostly static homepage but I wanted to have partial views that for navigation, footer ect. I'm using ejs and it looks like this:
my controller: home.js
// Dependencies
var express = require('express');
module.exports = {
get: function(req, res) {
app.set('view engine', 'ejs');
var model = {
layout:'home',
};
res.render('home');
}
};
My views directory has nav, home and footer all .ejs
Then the actual html file stripped of text would look as following.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" >
<title>Tom Jones</title>
<!-- CSS -->
<link rel="stylesheet" href="/css/home.css" type="text/css" media="screen" >
</head>
<body>
<%- partial('nav') %>
<!--content part -->
<div id="showcontainer">
<section>
</section>
</div>
<div id="maincontainer">
<section>
</section>
</div>
</body>
</html>
The Problem
When ever I test it out I run into the error partial is not defined. I tried requiring ejs but no success.
As #Pickels said, Partial was removed in 3.x. However, the most recent version of EJS provides a mechanism for including "partials", called "include":
https://github.com/visionmedia/ejs#includes
Includes are relative to the template with the include statement, for example if you have "./views/users.ejs" and "./views/user/show.ejs" you would use <% include user/show %>. The included file(s) are literally included into the template, no IO is performed after compilation, thus local variables are available to these included templates.
The following will work as a replacement for your old partial() function. You'll need to make tweaks elsewhere to support Express 3.x completely, but for the most part this seems to work well (better actually - less code and more performant).
<% include nav.ejs %> <!-- replaces your old <%- partial('nav') %> -->
Now in ejs 3.1.x
<% include('relative_filepath'); %>
Must be replaced by
<%- include('relative_filepath'); %>
Partial was removed in 3.x. It's now up to the templating engine to provide partials.

Resources