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.
Related
This question already has answers here:
How can I download a file using window.fetch?
(10 answers)
Closed 9 months ago.
I am working in a fullstack project I have backend folder using nodejs with server.js file of the following code
const express = require("express");
const cors = require("cors");
const path = require("path");
const app = express();
app.use(express.static(path.join(__dirname, "puplic/uploads")));
app.use(cors());
app.get("/", async (req, res) => {
res.download("b.rar");
});
app.listen(3000, () => {
console.log("server connected");
console.log(path.join(__dirname, "puplic/uploads"));
});
and client side of index.html of the following code
<!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>Document</title>
</head>
<body>
<button id="btn">press</button>
<script src="index.js">
</script>
</body>
</html>
and client side index.js of the following code
let btn=document.getElementById("btn")
btn.onclick=()=>{
fetch("http://localhost:3000/",{
method:"GET",
mode:"cors"
}).then(res=>
{
}
)
}
how i can fetch the server side and download the file in the client pc
when the client press the button
I would recomment to redirect to a blank page and set a download header there.
Client side would look like this:
let btn=document.getElementById("btn")
btn.onclick=()=>{
window.open("http://localhost:3000/", '_blank')
}
on the serverside you have to set a download header, code would look like this:
app.get("/", async (req, res) => {
res.download("b.rar");
});
optional you can set the headers by yourself using:
app.get("/", async(req, res) =>.{
res.set({
"Content-Disposition": "attachment; filename=\"b.rar\"",
"Content-Type": "application/x-rar-compressed, application/octet-stream"
});
const fs = require('fs/promise');
fs.readfile('./b.rar').then(file => {
res.send(file);
})
});
I havent tested this whole stuff but maybe it can help you. Optional it is enough to use an tag instead of a button and manage the redirection there since some browsers deny window.open from javascript due to cross site injection.
I create a server using nodejs with express
server.js
const express = require('express');
const app = express();
const path = require('path');
const router = express.Router();
router.get('/',function(req,res){
res.sendFile(path.join(__dirname+'/index.html'));
//__dirname : It will resolve to your project folder.
});
//----------------------------------------------------------------------
//add the router
app.use(express.static(__dirname + '/View'));
//Store all HTML files in view folder.
app.use(express.static(__dirname + '/Script'));
//Store all JS and CSS in Scripts folder.
app.use('/', router);
app.listen(process.env.port || 3000);
And use html with javascript.
index.html
<html>
<head>
<meta charset="utf-8"/>
</head>
<link rel="stylesheet" href="./index.css">
<script type="text" src="./server.js"></script>
<script src="./index.js"></script>
<body>
<h1>Automatico</h1>
<button onclick="autohabilitar();">Habilitar</button>
<button onclick="autodeshabilitar();">deshabilitar</button>
<br>
<h1>Foco-1</h1>
<button onclick="f1habilitar();" id="f1h">Habilitar</button>
<button onclick="f1deshabilitar();"id="f1d">deshabilitar</button>
</body>
</html>
index.js
document.getElementById("f1h").disabled=true;
document.getElementById("f1d").disabled=true;
}
function autodeshabilitar(){
document.getElementById("f1h").disabled=false;
document.getElementById("f1d").disabled=false;
}
function f1habilitar(){
document.getElementById("f1h").disabled=true;
document.getElementById("f1d").disabled=false;
}
function f1deshabilitar(){
document.getElementById("f1d").disabled=true;
document.getElementById("f1h").disabled=false;
}
I need the function
function apagarf1(){
led1.off();
}
located in server.js for use in onclick of the button...
I tried export the function, import the script in the html, use johnny-five in another script...
I’m not super familiar with Johnny 5. But I do know you can’t access node.js specific stuff from the browser.
Your best bet will be to set up a basic api endpoint in express that you call from your front end code. When that endpoint gets hit you can trigger your nodejs function to turn the led off.
In your server file add this:
app.get('/led-off', (req, res) => {
apagarf1()
return res.send('LED off');
});
On your front end make a fetch() call to that endpoint and that should work.
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
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.
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>