Do I only have to use a templating language with express render? - node.js

I am learning node and express from the simplest and when rendering views using res.render('view',{data:data}) is it only a template engine like jade that fits in view. can I not use a normal html?

You can, but this is a problem I ran into when I was learning Node. If you do not want to use a templating engine, you can still have Node just spit out the contents of your HTML file in a static way. For example (VERY BASIC EXAMLE):
var base = '/path/to/your/public_html',
fs = require('fs'),
http = require('http'),
sys = requrie('sys');
http.createServer(function (req,res) {
path = base + req.url;
console.log(path);
path.exists(path, function(exists) {
if(!exists) {
res.writeHead(404);
res.write('Bad request: 404\n');
res.end();
} else {
res.setHeader('Content-Type','text/html');
res.statusCode = 200;
var file = fs.createReadStream(path);
file.on("open",function() {
file.pipe(res);
});
file.on("error",function(err) {
console.log(err);
});
}
});
}).listen(80);
console.log('server on tcp/80');

The great thing about Node is that it forces you to separate templates from logic (to a certain level, you can squeeze a lot of logic into template anyway).
I didn't like Jade and used EJS until it turned out that client-side EJS is different from server-side and you cannot really re-use templates in the browser (as you would definitely want at some point, when you start rendering pages in the browser). You can re-use simple EJS templates but you cannot re-use templates with partials (as most of your templates will be).
After a lot of searching and trial-and-error I ended up using doT templates that are very fast (the fastest there is, actually), light-weight (only 140 lines of JavaScript), can be easily integrated in Express (by following the pattern of consolidate - you can't use consolidate directly with doT yet), can be used in the browser (the function to load partials will have to be different, but it is easy again).
doT seems to have features that I haven't seen in other templating engines, has a very elegant syntax that is the closest to handlebars (my favourite) but still allows normal JavaScript inside (that's why I chose EJS in the first place).

Related

Sending nested request to node.js web server

I am about to teach creating a simple web server in node.js to my students. I am doing it initially using the http module and returning a static page. The server code looks like this:
var http = require('http');
var fs = require('fs');
http.createServer(function(request, response) {
getFile(response);
}).listen(8080);
function getFile(response) {
var fileName = __dirname + "/public/index.html";
fs.readFile(fileName, function(err, contents) {
if (!err) {
response.end(contents);
} else {
response.end();
console.log("ERROR ERROR ERROR");
}
});
}
index.html looks like this:
<!DOCTYPE html>
<html>
<head>
<title>Static Page</title>
</head>
</body>
<h1>Returned static page</h1>
<p>This is the content returned from node as the default file</p>
<img src="./images/portablePhone.png" />
</body>
</html>
As I would expect, I am getting the index.html page display without the image (because I am not handling the mime-type). This is fine; what is confusing me is, when I look at the network traffic, I would expect to have the index.html returned three times (the initial request, the image request and one for favicon.ico request). This should happen, because the only thing the web server should ever return is the index.html page in the current folder. I logged the __dirname and fileName var and they came out correctly on each request and there were indeed three requests.
So my question is, what am I missing? Why am I not seeing three index.html response objects in the network monitor on Chrome? I know one of the students will ask and I'd like to have the right answer for him.
what is confusing me is, when I look at the network traffic, I would
expect to have the index.html returned three times (the initial
request, the image request and one for favicon.ico request)
When I run your app, I see exactly three network requests in the network tab in the Chrome debugger, exactly as you proposed and exactly as the HTML page and the web server are coded to do. One for the initial page request, one for the image and one for favicon.ico.
The image doesn't work because you don't actually serve an image (you are serving index.html for all requests) - but perhaps you already know that.
So my question is, what am I missing? Why am I not seeing three
index.html response objects in the network monitor on Chrome?
Here's my screenshot from the network tab of the Chrome debugger when I run your app:
The code that you actually wrote (originally, can't be sure you won't edit the question) just serves an index.html. There is nothing in there that could read any other file (like an image).
I don't think you should teach students that syntax/mechanism because it is outdated. For starters, do not teach them to indent with tabs or four spaces. Indent with 2 spaces for JavaScript. Also, it just doesn't make sense to teach ES5 at this point. They should learn ES2015 or later (ES6/ECMAScript 2016/whatever they call it). For the current version of Node out of the box (6.6 as of writing), this would be the equivalent of what you wrote:
const http = require('http');
const fs = require('fs-promise');
http.createServer( (request, response) => {
fs.readFile(`${__dirname}/public/index.html`)
.then( data => {response.end(data)} )
.catch(console.error);
}).listen(8080);
But what you seem to be trying to do is create a gallery script.
Another thing about Node is, there are more than 300,000 modules available. So it just absolutely does not make sense to start from 0 and ignore all 300,000+ modules.
Also, within about three months, 6 at the most, async/await will land in Node 7 without requiring babel. And people will argue that kids will be confused if they don't have enough time toiling with promises, but I don't think I buy that. I think you should just teach them how to set up babel and use async/await. Overall its going to make more sense and they will learn a much clearer way to do things. And then the next time you teach the class you won't need babel probably.
So this is one way I would make a simple gallery script that doesn't ignore all of the modules on npm and uses up-to-date syntax:
import {readFile} from 'fs-promise';
import listFilepaths from 'list-filepaths';
import Koa from 'koa';
const app = new Koa();
app.use(async (ctx) => {
if (ctx.request.querystring.indexOf('.jpg')>0) {
const fname = ctx.request.querystring.split('=')[1];
ctx.body = await readFile(`images/${fname}`);
} else {
let images = await listFilepaths('./images',{relative:true});
images = images.map(i=>i.replace('images/',''));
ctx.body = `${images.map(i=> `<img src = "/?i=${i}" />` )}`;
}
});
app.listen(3000);

Using variables amidst html in node.js

Here's the deal:
I already have node.js server which communicates with a database;
I need to create a webpage for people to access and check leader-boards
from the database (the server queries the database to show the users
with top 10 scores);
The example below shows a server responding with html;
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write('<!doctype html>\n<html lang="en">\n' +
'<head>\n<meta charset="utf-8">\n<title>Test web page on node.js</title>\n' +
'<style type="text/css">* {font-family:arial, sans-serif;}</style>\n' +
'</head>\n<body>\n<h1>Euro 2012 teams</h1>\n' +
'<div id="content"><p>The teams in Group D for Euro 2012 are:</p><ul><li>England</li><li>France</li><li>Sweden</li><li>Ukraine</li></ul></div>' +
'\n</body>\n</html>');
res.end();
}).listen(8888, 'address');
console.log('Server running at http://address:8888');
How would I go about to do something similar but instead the list would be the result of a query to the database?
Note:
I already know how to query, I only need to know how to have the results shows in the HTML code above
Thanks in advance
Most modern web applications solve this problem by using a template engine. You asked for something similar, and this is likely the better way to go about it.
A template allows you to have a file or simply a string with variable placeholders and then you can pass a model (in this case, your return value from the database) to the template, render it, and send that to the client.
Depending on the database you're using, you will have to likely start making your queries using Node.js's asynchronous patterns. Generally when you make a query in Node.js you will follow a pattern similar to
...
db.create({"name" : "rawr"},
function(err, data) {
if (err) {
// handle error
}
// build your template
// res.send the compiled HTML
});
...
Of course this all depends on the database that you're using, but generally it will look something like that. If you're comfortable with HTML I recommend looking into Handlebars.js but also loking at the link provided above for a few more and find one you like. Without a few more details such as constraints or database being used, this is about as much as I can say.

Is it possible to use PhantomJS and Node to dynamically generate PDFs from templates?

Background / Need
I am working with a group on a web application using Node.JS and Express. We need to be able to generate reports which can be printed as hard copies and also hard copy forms. Preferably we'd like to dynamically generate PDFs on the server for both reports and hand written forms. We're currently using EJS templates on the server.
Options
I was thinking that it would be convenient to be able to use templates to be able to build forms/reports and generate a PDF from the resulting HTML, however my options to do this appear limited as far as I can find. I have looked at two different possible solutions:
PhantomJS -- (npm node-phantom module)
PDFKit
EDIT: I found another Node.JS module which is able to generate PDFs from HTML called node-wkhtml which relies on wkhtmltopdf. I am now comparing using node-phantom and node-wkhtml. I have been able to generate PDFs on a Node server with both of these and they both appear to be capable of doing what I need.
I have seen some examples of using PhantomJS to render PDF documents from websites, but all of the examples I have seen use a URL and do not feed it a string of HTML. I am not sure if I could make this work with templates in order to dynamically generate PDF reports.
When a request for a report comes in I was hoping to generate HTML from an EJS template, and use that to generate a PDF. Is there anyway for me to use Phantom to dynamically create a page completely on the server without making a request?
My other option is to use PDFkit which allows dynamic generation of PDFs, but it is a canvas-like API and doesn't really support any notion of templates as far as I can tell.
The Question
Does anyone know if I can use PhantomJS with Node to dynamically generate PDFs from HTML generated from a template? Or does anyone know any other solutions I can use to generate and serve printable reports/forms from my Node/Express back-end.
EJS seems to run fine in PhantomJS (after installing the path module). To load a page in PhantomJS given a string of HTML, do page.content = '<html><head>...';.
npm install ejs and npm install path, then:
var ejs = require('ejs'),
page = require('webpage').create();
var html = ejs.render('<h1><%= title %></h1>', {
title: 'wow'
});
page.content = html;
page.render('test.pdf');
phantom.exit();
(Run this script with phantomjs, not node.)
I am going to post an answer for anyone trying to do something similar with node-phantom. Because node-phantom controls the local installation of PhantomJS, it must use asynchronous methods for everything even when the corresponding PhantomJS operation is synchronous. When setting the content for a page to be rendered in PhantomJS you can simply do:
page.content = '<h1>Some Markup</h1>';
page.render('page.pdf');
However, using the node-phantom module within node you must use the page.set method. This is the code I used below.
'use strict';
var phantom = require('node-phantom');
var html = '<!DOCTYPE html><html><head><title>My Webpage</title></head>' +
'<body><h1>My Webpage</h1><p>This is my webpage. I hope you like it' +
'!</body></html>';
phantom.create(function (error, ph) {
ph.createPage(function (error, page) {
page.set('content', html, function (error) {
if (error) {
console.log('Error setting content: %s', error);
} else {
page.render('page.pdf', function (error) {
if (error) console.log('Error rendering PDF: %s', error);
});
}
ph.exit();
});
});
});
A really easy solution to this problem is the node-webshot module - you can put raw html directly in as an argument and it prints the pdf directly.

Get return value of `include` in jade template

What I basically try to accomplish is to re-use jade partials/templates when getting data through a socket connection. Non working example:
socket.on('company_created', function(company) {
var html = include _company;
$('#companies ul').append(html);
});
Normally I had to create a new li and set the content like so (which is working as expected):
$('#companies ul').append($('<li>').text(company.name));
This is okay for a simple list, but if I had complexer list and stuff, this could get messy pretty quick, plus I had to write plain HTML again, so I figured re-using my already existing jade templates with all their goodness would be awesome, but had not luck, yet.
Any clue?
PS: Please do not tell my to use Ember, Backbone, Derby, Meteor, Angular or whatsoever.
Thanks in advance!
You can compile your jade sources to JS with jade.compile. Then include these sources in the client-side javascript, include jade's runtime.min.js, and refer to your jade templates as to normal JS functions in your client-side code.
For example,
server.js
app.get('/templates/:template.js', function (req, res) {
var template = req.params.template;
response.end([
"window.templates = window.templates || {};",
"window.templates[\"" + template + "\"] = " + jade.compile(template + ".jade", { client: true; });
].join("\r\n"));
});
client.js
$(function() { $("#placeholder").html(window.templates["content"]({user: "Daniel" })); });
content.jade
h1: Hello #{user}!
index.jade
!!!
html
head
script(src='/lib/jquery/jquery.js')
script(src='/lib/jade/runtime.min.js')
script(src='/templates/content.js')
script(src='/scripts/client.js')
body
#placeholder
Note that the code above might be syntactically incorrect and is provided solely to illustrate the idea.
we have a build step that compiles them to functions sort of like penartur mentioned. I dont use extend or include (which dont work on the client anyway ATM), but personally I find we have absolutely no need for that on the client at all since the DOM provides all the separation we need.

Mustache(-like) template engine for Express?

Is there a template engine for Express (node.js) which is based on Mustache or uses a similar syntax?
All I could find is haml, jade, ejs, jquery templates and one based on CoffeeScript (I write plain JS).
I want to write "normal" html, so only ejs and jqtpl would fit. I already use mustache with backbone so it would be best to also use it on the server side with Node.js
Just stumbled on this ancient thread but no one has mentioned consolidate.js, which seems to be the "right" way under Express 3 (refer to http://expressjs.com/faq.html). It also provides an easy way to switch/experiment with templating systems.
Here's a simple example - http://invitingthebell.com/2012/12/24/mustache-templates-in-express-3-0/.
Code, in case it disappears is:
var express = require('express')
, cons = require('consolidate')
, app = express();
// assign the mustache engine to .html files
app.engine('html', cons.mustache);
// set .html as the default extension
app.set('view engine', 'html');
app.set('views', __dirname + '/views');
// test mustache
app.get('/', function(req, res){
var viewdata = { 'test' : 'Hey now.'};
res.render('index', viewdata);
});
app.listen(3000);
The index.html file in the views directory:
<html>
<head><title>Some CMS</title></head>
<body>
<h1>Mustache</h1>
<p>What do you say?</p>
<p>{{test}}</p>
</body>
</html>
You could probably add Mustache as a rendering engine by following the Express manual:
View filenames take the form “.”, where is the name of the module >that will be required. For example the view layout.ejs will tell the view system to >require(‘ejs’), the module being loaded must export the method exports.compile(str, >options), and return a Function to comply with Express.
Edit:
From the Mustache manual under Usage:
Below is quick example how to use mustache.js:
var view = {
title: "Joe",
calc: function () {
return 2 + 4;
}
};
var output = Mustache.render("{{title}} spends {{calc}}", view);
In this example, the Mustache.render function takes two parameters: 1) the mustache >template and 2) a view object that contains the data and code needed to render the >template.
From the above I suspect you could just export Mustache.render, but I haven't tested it. The object literals used as data look the same, but if they do happen to be different, you could probably just wrap Mustache.render in a function that formats it correctly.
Edit: Xomby's wrapper link contains an example of how to wrap handlebars for express, Mustache should be similar.
Try Hogan.js http://twitter.github.com/hogan.js/
I think it's what Twitter and LinkedIn uses in production.
Here's a working example/tutorial on using NodeJS, ExpressJS and MustacheJS Template Engine:
http://devcrapshoot.com/javascript/nodejs-expressjs-and-mustachejs-template-engine
You can build out a complete web page like you normally would, placing the mustacheJS fields where you like. Use express to route to the page, use node fs.readFileSync(); to get the html file, use mustache to update the data on the page then spit it out to the client.
It's kinda neat. I hope it helps!
-A-
Have you already tried stache ? It is no longer maintained but you can follow some links and get more recent stuff ..
I found Handlebars.js which is an extension of the Mustache template system/language.
And there is a really simple wrapper to use it with Express.
Sure, the best way to do this is the post here:
http://iamtherockstar.com/blog/2011/11/21/using-mustache-templates-express-apps/
So far, this has worked great for me. The only problem I have found is not using partials at the root path for views. For example partials in view/partials - the engine by default only finds partials as view. Let me know if you figure that out!
Check out Handlerbars. " Handlebars provides the power necessary to let you build semantic templates effectively with no frustration.
Handlebars is largely compatible with Mustache templates. In most cases it is possible to swap out Mustache with Handlebars and continue using your current templates. Complete details can be found here " - Handlebars

Resources