Express-handlebars not filling out {{{body}}} - express-handlebars

Using express-handlebars#5.2.0 and express#4.17.1 using node on windows and still cant get it to render in the body:
File Setup:
testapp.js
[views]
main.handlebars
[views][layouts]
test.handlebars
//testapp.js
const express = require('express');
const exhbr = require('express-handlebars');
const app = express();
const port = 3031;
app.engine('handlebars', exhbr({}));
app.use(express.static('public'));
app.set('view engine', 'handlebars');
app.get('/', (req, res) => {
res.render('main', { layout: 'test' });
});
app.listen(port, () => console.log(`App listening to port ${port}`));
<!--test.handlebars-->
<h1>Test</h1>
<!-- main.handlebars -->
<!DOCTYPE html>
<html lang="en">
<body>
{{{body}}}
</body>
</html>
Only <h1>Test</h1> is returned and hasn't been inserted into the body.
I have also tried the following just to make sure its looking in the right spots.
res.render('doesnt_exist');
Error: Failed to lookup view "doesnt_exist" in views directory "c:\wamp\www\rethinkdb_rest\views\"
res.render('main', { layout: "doesnt_exist" });
Error: ENOENT: no such file or directory, open 'c:\wamp\www\rethinkdb_rest\views\layouts\doesnt_exist.handlebars'

Looks like I was putting the main.handlebars and test.handlebars in the wrong directories.
File Setup should be:
testapp.js
[views]
test.handlebars
[views][layouts]
main.handlebars
And the render function in testapp.js should be:
//testapp.js
const express = require('express');
const exhbr = require('express-handlebars');
const app = express();
const port = 3031;
app.engine('handlebars', exhbr({}));
app.use(express.static('public'));
app.set('view engine', 'handlebars');
app.get('/', (req, res) => {
res.render('test', { layout: 'main' }); //<----fixed
});
app.listen(port, () => console.log(`App listening to port ${port}`));

Related

can't see css with express.static()

I'm trying to deploy areact-app using express server but I've got a problem while trying to link the front and the back. The jsx pages are working, but the style is not.
Here is my server.js document:
const express = require("express");
const cors = require("cors");
const path = require("path");
const bodyParser = require("body-parser");
const cookieParser = require("cookie-parser");
require("dotenv").config({ path: "./config/.env" });
require("./config/db");
const { checkUser, requireAuth } = require("./middleware/auth.middleware");
const userRoutes = require("./routes/user.routes");
const messageRoutes = require("./routes/message.routes");
const app = express();
app.use(express.static(path.join(__dirname, "client/build")));
const corsOptions = {
origin: process.env.CLIENT_URL,
credentials: true,
allowedHeaders: ["sessionId", "Content-Type"],
exposedHeaders: ["sessionId"],
methods: "GET,HEAD,PUT,PATCH,POST,DELETE",
preflightContinue: false,
};
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.json());
app.use(cookieParser());
app.use(cors(corsOptions));
// jwt
app.get("*", checkUser);
app.get("/jwtid", requireAuth, (req, res) => {
res.status(200).send(res.locals.user._id);
});
app.use("/api/user", userRoutes);
app.use("/api/message", messageRoutes);
app.get("*", (req, res) => {
res.sendFile(path.join(__dirname + "/client/build/index.html"));
});
app.listen(process.env.PORT, () => {
console.log(`listening on port ${process.env.PORT}`);
});
and here 's my file organisation

Handlebar template not showing on nodemailer email

I'm trying to send an email using nodemailer with a template using handlebars, however, I can't get the template to show on the email. In network, the api that sends the email is showing the correct preview and response (in html) for what should be included in the template, but this information is not being displayed in the sent email. This is my first time doing this, and I have been trying to follow all the steps in examples/ tutorials on how to do this, but nothing seems to be working. I would really appreciate any help or advice on how to get my emails to send with the template. Thank you!
Note: orders.hbs is my handlebars document and is within the views folder
mailer.js
import express from 'express';
import expressAsyncHandler from 'express-async-handler';
import nodemailer from 'nodemailer';
import hbs from 'nodemailer-express-handlebars';
import handlebars from 'handlebars';
import Order from './models/orderModel.js';
import path from 'path';
import fs from 'fs';
const mailerRouter = express.Router();
/*
mailerRouter.engine('handlebar', exphbs());
mailerRouter.set('view engine', 'handlebars');
*/
mailerRouter.post (
'/order',
expressAsyncHandler(async (req, res) => {
const email = req.body.email
const orderId = req.body.orderId
const em = req.body.em;
const sender = req.body.sender;
const orderNum = req.body.orderNum
const emailBody = await Order.findById(orderId).lean()
if (emailBody) {
res.render('orders', {data: emailBody})
}
const sub = `Order: ${orderId}`
let transporter = nodemailer.createTransport({
host: 'smtp.gmail.com',
service: 'gmail',
auth: {
type: 'OAuth2',
user: sender,
pass: '',
clientId: '',
clientSecret: '',
refreshToken: '',
}
})
/*
transporter.use('compile', hbs({
viewEngine: 'express-handlebars',
viewPath:'./views/'
}))*/
const handlebarOptions = {
viewEngine: {
extName: '.hbs',
partialsDir: 'views',
layoutsDir: 'views',
defaultLayout: '',
},
viewPath: './views/',
extName: '.hbs',
};
transporter.use('compile', hbs(handlebarOptions));
const mailOptions = {
from: sender,
to: em,
subject: sub,
text: "Hello"
html: 'hi'
template: 'orders',
}
transporter.sendMail(mailOptions, function (err, info) {
if(err)
console.log(err)
else
console.log(info);
});
}))
export default mailerRouter;
server.js
import express from 'express';
import cors from 'cors';
import mongoose from 'mongoose';
import dotenv from 'dotenv';
import path from 'path';
import hbs from 'express-handlebars';
import orderRouter from './routers/orderRouter.js';
import mailerRouter from './mailer.js';
const app = express();
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
mongoose.connect(process.env.MONGODB_URL || 'mongodb://localhost/AM', {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
});
app.use('/api/orders', orderRouter);
const __dirname = path.resolve();
app.use('/api/mailer', mailerRouter);
app.engine('hbs', hbs({
extname: 'hbs',
defaultLayout: false,
layoutDir:__dirname+'/backend/views/layouts/',
partialsDir: __dirname + '/backend/views/layouts',
}));
app.set('views', path.join( __dirname, '/backend/views/layouts'));
app.set('view engine', 'hbs');
app.get('/', (req, res) => {
res.send('Server is ready');
});
app.use((err, req, res, next) => {
res.status(500).send({ message: err.message });
});
const port = process.env.PORT || 5000;
app.listen(port, () => {
console.log(`Serve at http://localhost:${port}`);
});
Edit:
So, if I have:
...
const __dirname = path.resolve();
const emailTemplateSource = fs.readFileSync(path.join(__dirname, "backend/views/orders.hbs"), "utf8")
const mailOptions = {
from: sender,
to: em,
subject: sub,
text: '',
html: emailTemplateSource,
// template: emailTemplateSource,
...
The email body shows:
{{#each data.orderItems}}
{{name}}
{{/each}}
Instead of the names of the items. I have also tried adding const temp = handlebars.compile(emailTemplateSource) after const emailTemplateSource and then changing it to html: temp, but this sends a blank email. I have also tried adding these after template: , but no matter what I put there nothing seems to show up.
Additional Info:
console.log(emailTemplateSource)
Gives :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
</style>
</head>
<body>
{{#each data.orderItems}}
<div>
<h3>{{name}}</h1>
</div>
{{/each}}
</body>
</html>
And
const temp = handlebars.compile(emailTemplateSource) console.log(temp)
Gives: Function: ret] { _setup: [Function (anonymous)], _child: [Function (anonymous)]}

While Ejs file doesn't see css style?

Have problem in my express app. Have some ejs templates, where css style file applied correctly. For example "localhost***/page", but when i go to "localhost***/page/secondpage" my ejs doesn't see style even if i apply it.
A little bit of code
app.js
app.use(express.static(path.join(__dirname, 'public')));
//some code
app.use('/', require('./routes/index'));
app.use('/events', require('./routes/events'));
some routes
const express = require('express');
const router = express.Router();
router.get('/', function (req, res, next) {
let query = *db query*;
res.locals.connection.query(query, function (error, results, fields) {
if (error) throw error;
res.render('index', { title: 'Events', data: results });
});
});
router.get('/:id', function (req, res) {
let query = *db query*;
res.locals.connection.query(query, function (error, results, fields) {
if (error) throw error;
res.render('singleevent', { title: 'Event', data: results });
});
});
Head of localhost***/events page and of next page localhost***/events/singleevent
<head>
<meta charset="UTF-8">
<title>
<%= title %>|Minsk Events</title>
<link rel="stylesheet" href="css/style.css">
</head>
There are my dirs
You asked for css file related to the html file.
So if html file is placed under events, then css file should be at:
/events/css/style.css
etc.

Node.js can't use external css file

I recently start learning node.js, and I got problem. I use express to acces my public file, everything work fine except css files. I did some research on the topic, and use everthing i found, but it dose not work.
My folder structure
app.js
pub
index.html
style.css
This is my html:
<!DOCTYPE html>
<html >
<head>
<title> Curriculum Vitae </title>
<meta charset="UTF-8">
<link rel="stylesheet" href="style.css"/>
</head>
<body>
...
</body>
</html>
And my app.js file:
var http = require('http');
var url = require('url');
var fs = require('fs');
var express = require('express')
var app = express();
var path = require('path');
app.use(express.static(path.join('pub', 'public')));
http.createServer(function (req, res) {
var q = url.parse(req.url, true);
var filename = "." + q.pathname;
fs.readFile(filename, function(err, data) {
if (err) {
res.writeHead(404, {'Content-Type': 'text/html'});
return res.end("404 Not Found");
}
res.writeHead(200, {'Content-Type': 'text/html'});
res.write(data);
return res.end();
});
}).listen(8080);
I think your problem is on this line :
app.use(express.static(path.join('pub', 'public')));
You are setting "/pub/public" as public folder, and you just need to set "/pub"
Can you try with something like this ?
app.use(express.static(__dirname + '/pub'));
Hope it helps.

Static CSS files not applied to expressJS app

I am trying by first express web app and I am using html to render my web pages and css to style my pages.
My directory structure is as follows
app.js
routes/
index.js
views/
index.html
public/
stylesheets/
style.css
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Devices</title>
<link ref="stylesheet" type="text/css" href="stylesheets/style.css">
</head>
<body>
<h1>DEVICES</h1>
<table>
<tr><th>#</th><th>DID</th><th>DeviceName</th><th>OS</th><th>Version</th><th>Numbers</th></tr>
</table>
</body>
</html>
I have linked the static CSS file using link tag
app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'styles')));
app.use('/', routes);
app.use('/users', users);
please note app.set('view engine', 'jade'); is left as it is as if i give html i am getting error.
index.js
var express = require('express');
var path = require('path');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.sendFile(path.resolve(__dirname , '../views/index.html'));
});
module.exports = router;
My issue is the static css file placed in public/stylesheets is not applied to my html when rendered.When I execute http://localhost:3000/stylesheets/style.css, I able to see the contents of style.css is returned.
I am not quite sure what I am doing wrong
Thanks
Try changing how you set the path to your static assets.
app.use(express.static(__dirname + '/public'));
app.use(express.static(__dirname + '/styles'));

Resources