Setting up the directory management in Express Handlebars - javascript

I use NodeJs, Express and Handlebars.
My server file app.js
const express = require('express');
const exphbs = require('express-handlebars');
const app = express();
app.engine('handlebars', exphbs({defaultLayout: 'index'}));
app.set('view engine', 'handlebars');
app.get('/start', function (req, res) {
res.render('start'); // render the "start" template
});
app.listen(8888, function () {
console.log('Server running on port 8888');
});
So when passing in the route localhost:8888/start there should be my index.handlebars
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Foo</title>
</head>
<link href="../../CSS/requirements.css" rel="stylesheet">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<body>
<p>TEST - This is on all pages</p>
{{{body}}}
</body>
</html>
and the template to load (start.handlebars)
<script src="../Client/start.js"></script>
<p>Template 1 is active</p>
My directory structure
When running the server, my route is loading fine but the problem is, that the browser is not able to find the script and css files.
I checked my paths but I think they might be correct. Am I wrong?

You have to set static folder in your express app. Add following middleware
app.use(express.static(path.join(__dirname, 'public')));
right after
app.set('view engine', 'handlebars');
Create a public folder at your root level and move your Client and CSS folder in that public folder.
Ref: Link

Related

Unable to load CSS file within nodeJS app

I have an app that I followed from a tutorial for the backend in nodeJS and Express. My connection to MongoDB via Mongoose is working. However, I've been trying to add a front-end- at the moment- just a simple html/ejs/css form. My endpoints are loading in localhost but only the html/ejs is rendering. My css file shows as plain code at http://localhost:3000/styles.css but isn't loading so I'm just getting plain html/ejs. I'm using VS Code. Here's my relevant code:
App.js:
const express = require('express');
const bodyParser = require('body-parser');
const product = require('./routes/product.routes'); // Imports routes for the products
const app = express();
var path = require('path');
const cors = require('cors');
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs')
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(cors({
origin: '*'
}));
app.use(express.static(path.join(__dirname, '/public')));
app.use(express.static(path.join(__dirname, 'views')));
app.use("/styles", express.static(__dirname + '/styles'));
app.use('/product', product);
let port = 3000;
app.listen(port, () => {
console.log('Server is up and running on port number ' + port);
});
Product.routes.js
const express = require('express');
const router = express.Router();
// Require the controllers WHICH WE DID NOT CREATE YET!!
const product_controller = require('../controllers/product.controller');
// a simple test url to check that all of our files are communicating correctly.
router.get('/', product_controller.start);
router.get('/test', product_controller.test);
router.post('/create', product_controller.product_create);
router.get('/:book', product_controller.product_details);
router.put('/:book/update', product_controller.product_update);
router.delete('/:book/delete', product_controller.product_delete);
module.exports = router;
Product.controller.js
const Product = require('../models/product.model');
//Simple version, without validation or sanitation
exports.start = function (req, res) {
res.sendFile('index.html', { root: './views' })}
exports.test = function (req, res) {
res.render('index.ejs', { root: './views' })}
Index.ejs
<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>HTML 5 Boilerplate</title>
<link rel="stylesheet" type="text/css" href='/public/styles.css'/>
<base href="/">
</head>
<body>
<h1>BookBooker</h1>
<h2>A library app for personal use.</h2>
<form action="/create" method="POST">
<input type="text" placeholder="Writer" name="name" />
<input type="text" placeholder="Book" name="book" />
<button type="submit">Submit</button>
</form>
<script src="app.js" type="module" type='text/javascript'></script>
</body>
</html>
My file structure looks like:
CRUD folder
-app.js
-package.json
-package-lock.json
-controller folder
--product.controller.js
-public folder
--styles.css
-routes folder
--product.routes.js
-views folder
--index.html
--index.ejs
Apologies if it's obvious- I'm super new to this. As you can see, I've tried static files, paths, CORS, and lots of combinations of file routing but I'm getting myself in a big muddle. I've considered caching but the css isn't showing in Chrome, Edge or Incognito mode either. Any help would be appreciated.
Instead of
<link rel="stylesheet" type="text/css" href='/public/styles.css'/>
write
<link rel="stylesheet" type="text/css" href='/styles.css'/>
The public folder name is not part of the stylesheet URL, it is just the folder where express.static looks for files.
The CSS showing as plain text may be caused by a wrong Content-type in the header. The browser is interpreting it as a plain text file, instead of handling it as CSS. Before you send the response, you can set response headers in your controller like:
res.header('Content-type', 'text/css');
See Express Docs
Hope this helps.

How to apply css to to node.js?

In this code I'm calling an html file into app.js, the css style is not applied to the html but when I open the html path alone without the app.js the style is applied, here's the code:
const express = require("express");
const bodyParser = require("body-parser");
const ejs = require("ejs");
const mongoose = require('mongoose');
const app = express();
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(express.static("public"));
mongoose.connect("mongodb://localhost:27017/aqeldb1", {useNewUrlParser: true});
app.route("/order")
.get(function(req, res){
res.sendFile(__dirname + "/ordernow.html");
});
app.listen(3000, function() {
console.log("Server started on port 3000");
});
Use in your main .js file:
app.use('/css',express.static(__dirname +'/css'));
use in you main .html file:
<link rel="stylesheet" type="text/css" href="css/style.css" />
Please keep .css files in the public folder
You need to set as static the directory where the .css files are or /index.html won't be able to access them when loaded through the express server.
app.use(express.static("directory/that/you/want/to/be/publicly/accessible")); <-- here you keep .css, and clientside .js files.
You could also put the .css files in the public folder if you don't want to add another static directory. A good approach is to make all the directories that contain the view files (.html, .css, .js) static.
Try to apply app.use(express.static('public'));

Can't display an image with EJS file in node.js

i'm new to node.js and my just playing with it to make a website. I want to display a picture on the website and that picture is in the same directory as my ejs file, but it does not show up.. Am i doing something wrong ? Thank you !
Backend code
const express = require('express')
//Init App
const app = express();
//Load view engine
app.set('view engine','ejs');
// Home route
app.get('/', function(req,res){
res.render('index.ejs');
});
app.listen(3000, function(){
console.log('Server started in port 3000...');
});
ejs file content:
<!DOCTYPE html>
<html>
<head>
<title>Hello World!</title>
</head>
<body>
<h1>Picture test</h1>
<img src="/Users/aray/Documents/Projects/Node/views/test.jpg">
</body>
</html>
The project strcture is :
- Node
- app.js
- views
- index.ejs
- test.jpg
you have to put your images (and other assets) in separate folder and serve this folder with express.static:
app.use(express.static('public'));
- Node
- app.js
- views
- index.ejs
- public
- test.jpg
<img src="test.jpg">
further information can be found in the express documentation: https://expressjs.com/en/starter/static-files.html

Implement Posted Form from NodeJS into HTML

I recently switched from starting to learn PHP to NodeJS since I have more knowledge in JS. My question is how do I display posted form data into a HTML File?
server.js
const app = require('express')(),
bodyParser = require('body-parser'),
path = require('path');
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.get('/', (req, res) => res.sendFile(path.join(__dirname, 'html/index.html')));
app.post('/student', (req, res) => res.send(req.body.user.name));
app.listen(3000, (req, res) => console.log('Listening on port 3000.'));
html/index.html
<body>
<form method='post' action='post'>
<input type='text' name = 'user[name]'>
<input type='submit' value='submit'>
</form>
</body>
However in the post method, I want to send a HTML file, instead of req.body.user.name which I could obviously do like I did on the home page (/), I want to be able to include some variables into the new HTML File, maybe something looking along the lines of:
<body>
<h1><? req.body.user.name + 's page. ?></h1>
<!-- rest of code -->
</body>
I use ejs template for this purpose and it is very easy to use.
First of all, download ejs with npm install ejs -s and create a views folder inside your main directory. Inside that folder, create a normal html file but this time with an extension of .ejs.
App Directory
-views/myFile.ejs
/post.ejs
-html/index.html
-server.js
Now let's go to your server.js file. You need to use app.set('view engine', 'ejs') to run ejs. When you do res.render() you don't have specify the path because the program already looks for views/ folder in the main directory.
const app = require('express')(),
bodyParser = require('body-parser'),
path = require('path');
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.set('view engine', 'ejs');
app.get('/', (req, res) => res.render('myFile.ejs', {username: 'myUser'}));
app.post('/student', function(req, res){
var username = req.body.user.name;
res.render('post.ejs', {user: username});
});
app.listen(3000, (req, res) => console.log('Listening on port 3000.'));
This is our sample myFile.ejs
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<p><%=username%></p>
</body>
</html>
And this is our sample post.ejs
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<p><%=user%></p>
</body>
</html>
You should use some template engine, there is tutorial on express page https://expressjs.com/en/guide/using-template-engines.html.
There is always possibility that you can write your own module for handling this.
You can also install express generator
npm install express-generator -g
then call:
express
Thanks to this you will setup express project with jade as template engine(it is default), it should allow you to progress further.

Express fallback route also used for static files

I am trying to create an express application that works with React and React-router on the front end. So I'm loading the index.html file and let react router handle the rest of the routing. But when refreshing on a page with a react router url that doesn't have an express route I obviously get the message {cannot GET .....}. So i added a fallback route after all my routes to always return index.html when there is no route.
So now I have routes to "/api/...", "/" and "*", I am also serving static files from "/public/build" and "/app/src/static/". When calling the "/" everything works great, when calling the "*" the index.html gets loaded, but the index.js and styles.css files are both loaded with the content from index.html. So my browser gets a styles.css file with a bunch of html in it whereas when using the "/" route the .js and .css files get loaded correctly.
So navigating to "/" loads the index page correctly with all the static files. I can then use my react-router-dom NavLink to navigate to difirent views without making a request back to the server. But when i try to load any react-router-dom page directly I get my index.html but my index.js has the same contents as index.html, same for styles.css
My code:
const app = express();
app.use(bodyParser.urlencoded({ extended: true}));
app.use(bodyParser.json());
passportConfig(passport);
app.use(passport.initialize());
app.use(passport.session());
app.use('/api/user', userRoutes);
app.use('/api', championRoutes);
app.use('/public/build', express.static(__dirname + '/public/ReactApp/build'));
app.use("/app/src/static/image", express.static(__dirname + '/public/ReactApp/src/static/image'));
app.use("/app/src/static/style", express.static(__dirname + '/public/ReactApp/src/static/style'));
app.get('/', (req, res) => {
res.sendFile(path.resolve(__dirname, '..', 'index.html'));
});
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, '..', 'index.html'));
});
app.listen(8080, () => {
console.log('started on port 8080');
});
The userRoutes and championRoutes variables both contain an express.Router object that has a few routes set.
Edit:
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
<link href="app/src/static/style/styles.css" rel="stylesheet" />
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<div id="app"></div>
<script
src="https://code.jquery.com/jquery-3.2.1.min.js"
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="public/build/index.js"></script>
</body>
</html>
<script src="public/build/index.js"></script>
This means that the location is relative to the current path, ie, if you are at http://somedomain.com/page2, the path to the index.js will be http://somedomain.com/page2/public/build/index.js (which in your case will serve the index.html file).
To specify a relative path from the base of your url instead, start the path with a /:
<script src="/public/build/index.js"></script>

Categories

Resources