how do I render a handlebars page from a routing module - node.js

I am learning nodejs with express platform. I generated an express project and there are 2 routing files that I edited. One routing file is "users.js" and it's supposed to render layou.hbs when '/users' is requested, the other is "index.js" and it's supposed to render "home.hbs" when '/' is requested. the problem is, when '/' is requested on the url box, i get layout.hbs output on the browser. What am i doing wrong?
Here is the code from the files.
index.js
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('home', {title:Express});
});
module.exports = router;
user.js
var express = require('express');
var router = express.Router();
router.get('/users', function(req, res, next) {
res.render('layout', {title:Express});
//res.send('respond with a resource');
});
module.exports = router;
Home.hbs
</!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<p>goodbye World</p>
</body>
</html>
layout.hbs
</!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<p> Hello World!</p>
</body>
</html>
if i visit localhost:3000, I expect to see "goodbye world" but I see "hello world", what is wrong with this code? Thank you.

In both the files you are rendering 'home'. In line res.render('home', {title:Express});
In user.js do this:
res.render('layout', {title:Express});
Cheers:)

You should remember to require express-hbs and tell express to use that. Your main app.js or any other names you gave that file should look like this.
var http = require('http');
var express = require('express');
var hbs = require('express-hbs'); //load handlebars
var app = express();
// setup hbs view engine
app.set('view engine', 'hbs');
//location of your views folder
app.set('views', __dirname + '/views');
http.createServer(app).listen(3000);

Whatever template you render, it will be loaded as the body of your layout. For this to work, your layout should look like:
</!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
{{{body}}}
</body>
</html>
The actual body contents should go in the template you render
home.hbs
<p> Hello World!</p>
goodbye.hbs
<p> Goodbye World!</p>
So doing
res.render('home');
Would show "hello world" whereas rendering
res.render('goodbye');
Would display "Goodbye world"
If you wanted to use a different layout to wrap a given template, you can override the default:
res.render('other', {layout: 'other_layout'});
BTW, passing the variable "title" as
{title: Express}
Means nothing. The "Express" variable isn't declared. You should instead use a defined variable or pass a string literal
{title: 'Express'}
And, to have it displayed in the generated HTML, the layout would use it like this:
</!DOCTYPE html>
<html>
<head>
<title>{{title}}</title>
</head>
<body>
{{{body}}}
</body>
</html>
Please note the body part has 3 curly braces whereas the template vars use only 2.

Related

Can Not Get file EJS Under Views Directory

In this problem, I tried to render ejs after update the data from UI. Here is my code,
const express = require("express");
const bodyParse = require("body-parser");
const date = require(__dirname + "/date.js");
const app = express();
const port = 3000;
app.set("view engine", "ejs");
app.use(bodyParse.urlencoded({ extends: true }));
var path = require('path');
let items = ["Buy Food", "Cook Food", "Eat Food"];
let itemWorks = [];
app.get("/", function (req, res) {
let day = date.getDay();
res.render(path.join(__dirname + "/views/list.ejs"), { listTitle: day, listItem: items });
items.pop;
app.post("/", function (req, res) {
let item = req.body.foodservice;
if(res.body.list === "work"){
itemWorks.push(item);
res.redirect("/work");
}else{
items.push(item);
res.redirect("/");
}
items.push(item);
res.redirect("/");
});
});
Here is my list.ejs:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>To Do List</title>
</head>
<body>
<h1><%=listTitle%></h1>
<ul>
<% for(var i = 0; i < listItem.length; i++){ %>
<li><%=listItem[i]%></li>
<% } %>
</ul>
<form action="/" method="post">
<input type="text" name="foodservice" placeholder="New Item" autocomplete="off"/><br /><br />
<button type="submit" name="button" value=<%=listTitle%>>+</button>
</form>
</body>
</html>
Here is my project's structure:
BRANDNEW_PROJECT views /list.ejs app.js data.js
However, when I have executed it=> errors have been displayed as bellow
TypeError: Cannot read properties of undefined (reading 'list')
at E:\WEB DEVELOPMENT\NodeJS\BrandNew_Project\app.js:25:15
I have tried to debug by putting log to check whether it already points to file that I want or not and the path is correct and also to tried set up file path like this:
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
However, the issues have not been resolved.
What can be the reason here? Thanks a lot for your help.
Live working URL : https://stackblitz.com/edit/node-dmtquz?file=index.js
Views folder is default in EJS.
Concept:
when render html pages you must take care path will start for other inside views as root
when render html pages you must take care path will start for other inside views as root.
Not render views/layouts/index use layout/index because,EJS make views (or your directory) as active directory for it.
if you want to change the directory use app.set("views", path.join(path.resolve(), < dir name >)).
Structure:
views
-------- layouts
---------------- index.ejs (this file i rendered as root)
-------- partials
-----------------footer.ejs, header.ejs etc
Hope this will clear up your problem
var express = require("express");
var app = express();
// set the view engine to ejs
// app.set("views", __dirname + "/views");
app.set("view engine", "ejs");
// use res.render to load up an ejs view file
// index page
app.get("/", function (req, res) {
res.render("layouts/index" , {
displayTitle: "items viewer",
item: ["item1", "item2"]
});
});
// about page
app.get("/about", function (req, res) {
res.render("layouts/about");
});
app.listen(8080);
console.log("Server is listening on port 8080");
<!-- root dir, views/layout/list.ejs -->
<!DOCTYPE html>
<html lang="en">
<body>
<%= displayTitle%>
<hr />
<% for (let i of items) { %>
<br />
<%= i %> <% } %>
</body>
</html>
I think you need to use path.resolve instead of path.join like this:
res.render(path.resolve(__dirname + "/views/list.ejs"), { listTitle: day, listItem: items });
You might also need to update your import of the date object at the top to use path.resolve like this:
const date = require(path.resolve(__dirname + "/date.js"));
In my code I use path.resolve anytime I use __dirname

local host not responding when ejs templates are added

local host is not loading when partials(ejs templates) are added to the pages.The page loads at first if the partials are not added.But once the partials are added the page no longer loads.Also no error is also being reported.The page keeps on loading and finally shows unable to reach the adress.
var express = require("express");
var app = express();
var bodyparser = require("body-parser");
app.use(bodyparser.urlencoded({extended: true}));
app.set("view engine", "ejs");
app.get("/", function(req , res){
res.render("landing");
});
app.get("/campgrounds", function(req,res){
res.render("campgrounds",{campgrounds:campgrounds});
});
app.post("/campgrounds",function(req,res){
var name = req.body.name;
var image = req.body.image;
var newCamp = {name: name, image:image}
campgrounds.push(newCamp)
res.redirect("/campgrounds");
});
app.get("/campgrounds/new", function(req, res){
res.render("new.ejs");
});
app.listen(3000, function(){
console.log("Yelp camp server has started");
});
when the headers are added to the the following page the page no longer loads
<%- include('partials/header.ejs') %>
<h1>landing page</h1>
view all campgrounds
<p>asdasdasda</p>
<%- include('partials/footer.ejs') %>
Please help!!!!
also here is the code for the header
<!DOCTYPE html>
<html>
<head>
<title>YELPCAMP</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" >
</head>
<body>
<p>header tabs</p>
You're missing a - from the closing tag:
<%- include('partials/header.ejs') -%>
...
<%- include('partials/footer.ejs') -%>
Thanks for the help ,
The problem was occurring because of an incorrect bootstrap cdn and the partials declaration.
Fixed those issues and the app is now working fine.

rendering in nodejs using express to html

I'm trying to get values from nodejs into HTML. I've seen lot of answers, but none of them is working.
here what I've done so far:
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<title>Page Title</title>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<link rel='stylesheet' type='text/css' media='screen' href='main.css'>
</head>
<body>
<div>
<a id="test" name="test"> <%=name%></a>
</div>
</body>
</html>
app.js
const express =require('express')
const app = express();
var os = require( 'os' );
var path = require('path')
const PORT = process.env.PORT ||2000;
app.engine('html', require('ejs').renderFile);
app.get('/',(req,res)=>{
res.sendFile(path.join(__dirname+'/index.html'))
})
app.get('/test', (req, res)=> {
var name = 454;
res.render( "/index.html", {name:name});
});
app.listen(2001)
I don't get what I'm doing wrong. but it doesn't work as expected.
any idea how may I solve this ?
thanks in advance !
First, create a folder views and put your index.ejs right there (though, I am not sure, the extension have to be .ejs).
Then set the engine with:
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
And change your routing to:
app.get('/', (req,res) => {
res.render('index', { name: 'Test' });
});
Edit: I have used the express application generator and also checked Using template engines with Express.
Edit: According to the extension .ejs:
One thing to note is that all files in which ejs syntax are used in
must be saved with a .ejs extension [...]
Taken from Using EJS as a Template Engine in your Express App, not from the official docs.

Pug does not replace parameters with values

The docs of Pug say all the parameters will be replaced with values if they have this form: #{parameter_name} This doesn't work for me.
My code:
//Template
doctype html
html(lang="en")
head
title= title
body
h1
Task is #{task_id}
p
task is #{task_id}
company is #{company_id}
//javascript
var express = require('express')
var app = express()
const util = require('util');
app.set('view engine', 'pug')
app.get('/', function (req, res) {
res.send('Hello World!')
})
app.locals.pretty = true
app.get('/task/:company_id/:task_id',function(req,res) {
res.render('task',{task_id: req.query.task_id,company_id: req.query.company_id});
});
app.listen(8080, function () {
console.log('Example app listening on port !')
})
And the output:
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
</head>
<body>
<h1>
<Task>is </Task>
</h1>
<p>
<task>is </task>
<company>is </company>
</p>
</body>
</html>
No variable was interpreted!!! What is wrong here? I am following the docs!!! (I am using latest version, installed yesterday)
Looks like you are refering to the query string instead of parameters in your nodejs
Please change your code to this
res.render('task',{task_id: req.params.task_id,company_id: req.params.company_id});
You need to use params not query

How do I render a page in Node.JS with hogan-express

How do I render a page in node (using a router) which just passes a value to the template engine for me to use?
So for instance (this is the real code):
var apiRouter = express.Router();
apiRouter.get('/myPosts', function(req, res){
userPostsModel.findOne({'profileID':req.session.facebookProfileId}, function(err, userPosts) {
if(userPosts) {
res.json({
posts : userPosts.posts
});
} else {
console.log('You do not have any posts');
}
})
})
And the template engine part (html file):
<!doctype html>
<head>
<meta charset="UTF-8">
<title>My Posts</title>
</head>
<body>
<p>Post 1</p>
<p>Post 2</p>
</body>
</html>
I am expecting this to render the page but instead, I am getting this (on the webpage):
{"posts":["12345667"]}
For my template engine, I am using 'hogan-express', as below:
app.engine('html', require('hogan-express'));
app.set('view engine', 'html');
I know the res.json may be wrong here but I am not getting anywhere with this. The documentation for node and the routers is all over the place!
As #Molda has answered in the comments, below, it should be like this:
res.render('template-name', { posts:userPosts.posts});
Tried it and worked for me.

Resources