Why does my swig template not render in my MEAN web app? - node.js

I am trying to learn the MEAN stack along with Swig templates. I’m coding from scratch, as I tried a MEAN framework but it generated a lot of files and it was too much for me to begin with.
Currently my Swig template index.html does not render the HTML. This is the output I am getting:
{% include 'header.html' %}
<br>Welcome to my test website
where as I am expecting following
This is coming from Header
<br>Welcome to my test website
Why is it not rendering?
Following is my folder structure:
--config
-config.js
--node_modules
-* //modules installed via npm link
--public
-header.html
-index.html
-package.json
-routes.js
-server.js
Below is the content of each file
config.js
var port = process.env.PORT || 8080;
module.exports = {
dburl: 'mongodb://localhost/test',
port: port,
templateEngine: 'swig'
}
header.html
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<p> This is coming from Header</p>
index.html
{% include 'header.html' %}
<p>Welcome to my test website</p>
</body>
package.json
{
"name": "test",
"version": "0.0.1",
"author": "Rukmaj Chandavar",
"dependencies": {
"express": "*",
"mongoose": "*",
"angular": "*",
"swig": "*",
"consolidate": "*"
}
}
routes.js
module.exports = function(app){
app.get('*',function(req, res){
res.send('index.html');
});
}
server.js
var express = require("express");
var app = express();
var mongoose = require("mongoose");
var config = require('./config/config');
var swig = require('swig');
var cons = require('consolidate');
mongoose.connect(config.dburl);
app.use(express.static(__dirname + '/public'));
app.set('views', __dirname + '/public');
app.engine('html', cons.swig);
app.set('view engine', 'html');
require('./routes') (app);
app.listen(config.port);
console.log('MeriDawat running on port ' + config.port)
Following are the version numbers of installed node modules
angular#1.2.18
consolidate#0.10.0
express#4.4.3
mongoose#3.8.12
passport#0.2.0
swig#1.3.2
I would appreciate any help in troubleshooting this to help me move forward. Thanks in advance.

I think this is the offending line, in routes.js:
res.send('index.html');
res.send() just sends the contents of the file back in the HTTP response.
To render a template and send the rendered results back, you want res.render() instead:
res.render('index.html')

Related

node js pass / send post data to html

Hello i'm new to node js and i am trying send / pass post data to html but i can't seem to get it to work And was hoping maybe someone could point me in the right direction on how i can.
Server code:
const express = require("express");
const bodyParser = require('body-parser');
const app = express();
app.use(express.static("public"));
app.use(bodyParser.urlencoded({ extended: true }));
app.get("/", (request, response) => {
response.sendFile(__dirname + "/views/index.html");
});
app.post('/sendInfo', (req, res) => {
try {
console.log(`firstname: ${req.body.firstname} lastname: ${req.body.lastname}.`);
var firstName = req.body.firstname,
lastName = req.body.lastname;
res.sendFile(__dirname + "/views/info.html", { fistname: firstName, lastname: lastName });
} catch (e) {
console.error("error", e);
}
});
const listener = app.listen(process.env.PORT, () => {
console.log("Your app is listening on port " + listener.address().port);
});
views/info.html code:
<html>
<head>
<title>My Site title</title>
</head>
<body>
<h1><%= fistname %></h1>
<h1><%= lastname %></h1>
</body>
</html>
Looks like you are using the EJS template engine. So, there are a number of things that are missing in your code.
You need to tell express that you are using EJS at the template engine
The view must have an extension of .ejs not .html
You should be using res.render() and pass in the template name and the JSON data which will be used in the template
Set up a Node.js project using npm init -y, then run npm install express ejs, then create the app.js file (code given below) and finally create the views/index.ejs file (code given below). The views directory should be at the same level as your node_modules directory.
// app.js
const express = require('express');
const bodyParser = require('body-parser');
const port = process.env.PORT || 3006;
const app = express();
app.use(express.static(__dirname + '/build'));
app.use(express.json())
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json({ extended: true }));
app.set('view engine', 'ejs');
app.get('/fn/:first_name/ln/:last_name', (req, res) => {
res.render('index', {
first_name: req.params.first_name,
last_name: req.params.last_name
});
});
app.listen(port, () => {
console.log(`App listening on port ${port}`);
});
// views/index.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>First name is <%= first_name %></div>
<div>Last name is <%= last_name %></div>
</body>
</html>
Your package.json file must look something like this, use the start script
{
"name": "node-template",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node app.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"ejs": "^3.1.5",
"express": "^4.17.1"
}
}
Run the app using npm start
Finally, open up a browser and hit http://localhost:3006/fn/John/ln/Doe
If all goes well you will see an html rendered in the browser like this...
First name is John
Last name is Doe
Output:
Good luck.
Note: For the sake of simplicity I used GET instead of POST and used path params instead of request body. But the template engine works the same way.

Issue with partials using EJS in express

Just to preface: I've recently been transitioning my web development skills from PHP + HTML/CSS to Nodejs, but have been having trouble with templating.
I'm using Express, and after some research tried to use Pug.js, but found that too complicated for what I'm trying to achieve at the moment, so I moved to ejs as it seemed to be more simple.
What I'm trying to get is to be able to reuse HTML that I have already written for multiple pages on the site - which from what I've found is called 'partials'?
Now to the code I've written so far:
server.js:
var express = require('express');
app = express();
publicFolder = __dirname + '/public';
app.set('view engine', 'ejs');
app.use(express.static(publicFolder, {
extensions: ['html']
}));
app.listen(80, () => {
console.log('Server is online on port 80')
});
index.html: (/public/index.html)
<html>
<body>
<% include ../views/header.ejs %>
</body>
</html>
header.ejs: (/views/header.ejs)
<h1>Test header</h1>
I understand I may be on the completely wrong track, but any help would be greatly appreciated.
Regards
EDIT: I've double checked to make sure it's not a path issue
It might be easier for you to store all your view files as ejs in the same folder and user the path module to set your static files.
server.js:
var express = require('express');
var path = require('path')
app = express();
app.use(express.static(path.join(__dirname, 'public')));
app.set('views', path.join(__dirname, 'views'))
app.set('view engine', 'ejs')
app.listen(80, () => {
console.log('Server is online on port 80')
});
index.ejs
<html>
<body>
<% include header %>
</body>
</html>
Just a consideration. Hope it helps!

Node/Express with Angular 2

I am trying to build the ToDo app with the MEAN stack and I can't get the Express server to connect to Angular 2. I believe it has something to do with where I have my index.html view relative to the Angular installation, but I can't figure it out.
The error I am getting is the HTML on index.html is rendering but not picking up the logic behind the selector so my assumption is my tags are wrong or something. I have tried every which way to adjust the tags, but I can't get it to work when running server.js. I know it is something silly but been working on this for a while.
Server.js
var express = require('express');
var path = require('path');
var bodyParser = require('body-parser');
var index = require('./routes/index');
var todos = require('./routes/todos');
var app = express();
// View Engine
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.engine('html', require('ejs').renderFile);
app.use(express.static(path.join(__dirname,'client'))); //folder where angular will be
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use('/', index);
app.use('/api/v1/', todos);
app.listen(3000, function(){
console.log('Server started on port 3000...');
});
Index.html (in Views folder)
<!DOCTYPE html>
<html>
<head>
<title>Angular QuickStart</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="src/styles.css">
<!-- Polyfill(s) for older browsers -->
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="src/systemjs.config.js"></script>
<script>
System.import('src/main.js').catch(function(err){ console.error(err); });
</script>
</head>
<body>
<my-app>Loading AppComponent FROM SERVER SIDE content here ...</my-app>
</body>
</html>
app.module.ts
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { AppComponent } from './app.component';
#NgModule({
imports: [ BrowserModule ],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
app.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
template: `<h1>Hello {{name}}</h1>`,
})
export class AppComponent { name = 'Angular'; }
Below are the two errors I am getting in the console:
GET http://localhost:3000/src/app/app.module 404 (Not Found)
scheduleTask # zone.js:1960 ZoneDelegate.scheduleTask # zone.js:349
(404 Not Found) loading http:…pp.module" from
http://localhost:3000/src/main.js", originalErr:
ZoneAwareError}
Any help would be much appreciated, I can't get past this.
It is not liking something about the reference in this line and getting lost somewhere in zone.js, but I can't get it right. I am using the starter kit from angular.io and using their file layout.
System.import('src/main.js').catch(function(err){ console.error(err); });
I was able to fix by adding two more static routes to the express server so it looked in every folder.
app.use(express.static(path.join(__dirname, 'client'))); // folder where angular will be installed
app.use(express.static(path.join(__dirname, 'client', 'src')));
app.use(express.static(path.join(__dirname, 'client', 'src', 'app')));
This fixed the issue.
I have encountered the same problem with the new version of Quickstart. The fact that it has a different structure (src folder added) affects how express will behave. In my scenario I have NOT altered this portion.
System.import('src/main.js').catch(function(err){ console.error(err); });
Instead I left it as default (I believe angular handles where to look for it).
System.import('main.js').catch(function(err){ console.error(err); });
I have added one more static route. Make sure you have both, one of them will not suffice.
app.use(express.static(path.join(__dirname, 'client')));
app.use(express.static(path.join(__dirname, 'client/src')));
if you are following the TRAVERSY MEDIA: (original Source is EDUONIX)
https://www.youtube.com/watch?v=PFP0oXNNveg&t=2304s
after creating the 'client' folder. Skip the whole JSON Part.
Open Terminal
git clone https://www.github.com/angular/quickstart client
npm install
npm start (this will give you the complete start of the angular front-end)
ctrl + C (close the webserver)
npm run build
server.js
var express = require ('express');
var path = require ('path');
var bodyParser = require ('body-parser');
var index = require ('./routes/index');
var todos = require ('./routes/todos');
var app = express();
//View Engine
app.use(express.static( path.join(__dirname, 'client') ) );
app.use(express.static( path.join(__dirname, 'client/src')));
app.use(express.static( path.join(__dirname, 'client/bower_components')));
app.set('views', path.join(__dirname, 'client/src') );
app.set('view engine', 'ejs');
app.engine ('html', require('ejs').renderFile );
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false} ));
app.use('/', index);
app.use('/api/v1', todos);
app.listen(3000, function() {
console.log ('server started on port 3000');
/routes/index.js
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
res.render('index.html');
});
module.exports = router;
Last but not the least:
make sure this route would execute:
http://localhost:3000/api/v1/todos
yes? (you did it)

less-middleware not compiling, getting 404

I have a node.js server running with less-middleware. From my understanding, it compiles on the fly and places the css file in the destination/same(if not specified) folder.
My problem is I'm getting a 404 error on the get request for the css file:
Err: GET http://webserver/public/less/blog-reset.css 404 (Not Found)
Here is what I'm working with:
web.js
//requiring dependencies
var express = require("express");
var logfmt = require("logfmt");
var lessMiddleware = require('less-middleware');
var hogan = require('hogan-express');
var path = require('path');
//all environments
var app = module.exports = express();
var port = Number(process.env.PORT || 5000);
app.use(logfmt.requestLogger());
app.use(lessMiddleware(path.join(__dirname,'public')));
app.use(express.static(path.join(__dirname,'public')));
app.set('layout',path.join(__dirname,'src','views','blog-layout'));
app.enable('view cache');
app.engine('.html',hogan);
//page routing called after env loads
require('./src/router');
//listening port
app.listen(port, function() {
console.log("Listening on " + port);
});
blog-layout.html
<head>
<title>EpiBlog</title>
<link href='/public/less/blog-reset.css' rel='stylesheet' type='text/css'/>
</head>
<body>
{{{yield}}}
</body>
directory layout
ROOT
public
less
src
web.js
Versions
less-middleware v0.2.1-beta
express v4.0.0
What I've tried:
using app.use(lessMiddleware)({ src: __dirname + '/public' })); (apparently the old way of doing it)
using app.use(lessMiddleware(path.join(__dirname,'public','less')));
moving app.use(express.static(path.join(__dirname,'public'))); from web.js to router.js
toying with different paths
moving contents of router.js to web.js
specifying the destination using
this:
app.use(lessMiddleware(path.join(__dirname, 'source', 'less'), {
dest: path.join(__dirname, 'public')
}));
the problem was:
<link href='/public/less/blog-reset.css' rel='stylesheet' type='text/css'/>
should have been:
<link href='/less/blog-reset.css' rel='stylesheet' type='text/css'/>
i read that:
link(rel='stylesheet', type='text/css', href='css/styles.css')
was paired with directory structure:
myapp
+-public
+-css
+-styles.less
which led me to believe that this call:
app.use(express.static(path.join(__dirname,'public')));
makes the request assume /public/ is the parent so i was being redundant calling /public/less/blog-reset.css
reference was found here: express.js less compiler: can not get work

layout.ejs doesn't work on NodeJS app in Heroku

I have the usual nodejs express app...
var express = require('express');
var app = express.createServer(
express.bodyParser()
);
app.configure( function () {
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use("/public", express.static(__dirname + '/public'));
});
app.get('/', function (req, res) {
res.render('index');
});
I have a index.ejs and layout.ejs in /views folder:
layout.ejs:
<!doctype html>
<html lang="en" manifest=""><head>
<title>jQuery Plugin Demo</title>
</head>
<body>
<div class="container container-fluid">
<%- body %>
</div>
</body>
</html>
index.ejs:
Hello world
index.ejs only renders the "Hello world" text without the surrounding layout.ejs wrapper. The ejs is working. It's able to find the correct .ejs template, but it's just ignoring the layout. I've also tried explictly adding layout file to app..
app.set('view options', { layout:'layout.ejs' });
All of this works fine locally, but not on Heroku. Here is my package.json:
{
"name": "in1-test",
"version": "0.0.1",
"author": "Iatek",
"dependencies": {
"express": ">=2.5.x",
"ejs": ">=0.7.x"
},
"engines": {
"node": "0.6.x"
}
}
Why no joy on the layout??? Thanks
I'm using express 3.x with ejs-locals and it works well. You just have to specify which layout to use:
login.ejs
<% layout('layout') -%>
<form>...</form>
layout.ejs
<body>
<h1>Hello</h1>
<%- body %>
</body>
https://npmjs.org/package/ejs-locals
When you deploy to Heroku it does an npm install for all your dependencies; because you have stated express >=2.5.x it will install the latest which is 3.0.0_betax. Express 3 does not have support for layouts in ejs (yet).
To fix remove the ">=" and specify the version of express that is in your local version.
As chovy said, ejs-locals can help you handle this if you want to upgrade to Express 3.x. I've got a github repo here that provides a bootstrapped project for Express 3.x, ejs, and twitter bootstrap:
https://github.com/cacois/node-express-twitter-bootstrap
Its a good starting point for a new app, or as an example of how to use ejs layouts with Express 3.x.

Resources