Why is the directory throwing 404 when rendering ejs - node.js

I am trying to make a page which just receives a get request from my index.js file and just displays "hello user". I have created a 'users.ejs' file in my express app which just renders a string from a 'users.js' file. There is a form in my index.ejs file which redirects to my users directory. The index file works well when I type the '/' directory in the url box but for some reason, the file throws a 404 not found error in the browser when I hit the submit on the form in the first page instead of showing the 'users.ejs' page, can anyone tell me why it does this?
index.ejs
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<h1><%= title %></h1>
<p>Welcome to <%= title %></p><br>
<form action='/users' method='get'>
Enter Name: <input type='text' name='thetext'></input><br><br>
<input type='submit' id='checkresponse'>enter</button>
</form>
<script type = 'text/javascript' src = '/dist/jquery.js'></script>
<script type = 'text/javascript' src = '/js/response.js'></script>
</body>
</html>
index.js
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Expr-Ass' });
});
module.exports = router;
users.js
var express = require('express');
var router = express.Router();
/* GET users listing. */
router.get('/users', function(req, res, next) {
res.render('users', {star:'Sparksiano'});
});
module.exports = router;
users.ejs
<!DOCTYPE html>
<html>
<head>
<title><%= star %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<h1>Welcome user!</h1>
</body>
</html>

Based off of comments below you may want to try something like this:
users.js
var express = require('express');
var router = express.Router();
/* Notice the path change */
router.get('/', function(req, res, next) {
res.render('users', {star:'Sparksiano'});
});
module.exports = router;
It sounds like you may be mounting your path to include a /users and then having a route that has a path of /users. Would be easier to troubleshoot if you posted the rest of the server side code.

I place the various ejs files in a folder and then point the express router to use that folder as a path:
var app = express();
app.set('port', 6000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
Then I route them to those pages:
app.get('/', function (req, res) {
res.render('index', {title: 'Express'});
});
app.get('/users', function (req, res) {
res.render('users', {star:'Sparksiano'});
});
Make sure the users.ejs page is in the same folder.

Related

Node.js/Express post route failing

Trying out Node.js for the first time. My POST route is failing with "Cannot POST /admin/add-product.html". GET request is being served fine from the same route. I have had a look around here. Several answers to similar issues but nothing is helping. Here is my code:
./index.js
const path = require('path');
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const adminRoutes = require('./src/routes/admin');
const shopRoutes = require('./src/routes/shop');
app.use(bodyParser.urlencoded({ extended: false }));
app.use('/admin', adminRoutes);
app.use(shopRoutes);
app.listen(3000);`
./src/routes/admin.js
const path = require('path');
const express = require('express');
const router = express.Router();
// served on /admin/add-product GET route
router.get('/add-product', (req, res, next) => {
res.sendFile(path.join(__dirname, '../', 'views', 'add-product.html'));
});
// served on /admin/add-product POST route
router.post('/add-product', (req, res, next) => {
console.log(req.body);
res.redirect('/');
// res.send('<h1>product saved</h1>');
});
module.exports = router;
./src/views/add-product.html
<!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>Add Product</title>
</head>
<body>
<header>
<nav>
<ul>
<li>Shop</li>
<li>Add Product</li>
</ul>
</nav>
</header>
<main>
<form action="/admin/add-product.html" method="POST">
<input type="text" name="title" /><button type="submit">
Add Product
</button>
</form>
</main>
</body>
</html>
Thank you!!!
The action in the form need to match the route declare in the NodeJS application, it should be :
<form action="/admin/add-product" method="POST">
Remove the .HTML from the action attribute of the form.

Why do i get "The partial header could not be found" error when I set up my hbs files this way?

I am getting this error "Error: C:\Users\Don-Alex Antoine\Desktop\Daily-Scripture\templates\views\home.hbs: The partial headers could not be found" when I run my node app.
This is the code inside my app.js file
const express = require('express');
const path = require('path');
const hbs = require('hbs');
const body = require('body-parser');
const request = require('request');
const app = express();
app.listen(process.env.PORT|| 3000,()=>{
console.log('server is listening on port 3000');
});
//Defined path for express config
const publicDirectoryPath = path.join(__dirname, "../public");
const viewsPath = path.join(__dirname, '../templates/views');
const partialsPath = path.join(__dirname, '../templates/partials');
app.use(express.static(publicDirectoryPath));
app.set('views', viewsPath);
app.set('view engine', 'hbs');
hbs.registerPartials(partialsPath);
app.use(body.urlencoded({extended: true}));
app.get('/', (req, res)=>{
res.render('home');
});
Everything works perfectly until I change my header.hbs into this:
<!DOCTYPE html>
<html>
<head>
<meta>
<title>Daily-Scripture</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
my home.hbs file into this:
{{>headers}}
<h1>PlEASE WORK!!</h1>
{{>footer}}
and my footer.hbs file into this
<footer></footer>
</body>
</html>
Now when I add everything into the home.hbs file like this:
<!DOCTYPE html>
<html>
<head>
<title>Daily-Scripture</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<h1>PLEASE WORK</h1>
</body>
</html>
Everything works perfectly. I wanted to have a separate hbs file that contains the necessary headers such as the title, and the link to the stylesheet and use that in other hbs files if that's even possible. If you guys know what I'm doing wrong here I would appreciate the help.

NodeJs - route parameters crash the file system on a client

This is my server
const path = require('path');
const express = require('express');
const exphbs = require('express-handlebars');
const bodyParser = require('body-parser');
const handlebars = exphbs.create({
defaultLayout: 'index',
extname: 'hbs'
});
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
require('./Server/Routes/questionnaire')(app);
app.engine('hbs', handlebars.engine);
app.set('view engine', 'hbs');
app.use(express.static(path.join(__dirname, 'Public')));
app.listen(8888, function () {
console.log('Server running on port 8888');
});
and I use this route
module.exports = function (app) {
app.get('/questionnaire', function (req, res) {
res.render('questionnaire', {
eventInfo: {
description: "TEST",
imgHost: "Resources/img_logo.png"
}
});
});
};
the code works fine. When adding a parameter to the route /questionnaire/:id no css files or client code is found.
What am I missing? Using a parameter in my route should have the correct syntax. This error just appears, when using parameters in the routes.
EDIT:
The whole directory
First I use my default HTML index.hbs
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<link href="Style/base.css" rel="stylesheet">
<link href="Style/header.css" rel="stylesheet">
<link href="Style/button.css" rel="stylesheet">
<link href="Style/input.css" rel="stylesheet">
<link href="Style/link.css" rel="stylesheet">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<script src="Client/header.js"></script>
<body>
<div id="header">
</div>
{{{body}}}
</body>
</html>
and I render my questionnaire.hbs template
<link href="Style/Templates/questionnaire.css" rel="stylesheet">
<script src="Client/Templates/questionnaire.js"></script>
<div id="content">
</div>
As mentioned in the comments, I have to write /....
When using a parameter, it seems I have to write full paths like
"/Resources/img_logo.png"
instead of
"Resources/img_logo.png"
Try this in your app.js
//comment this line
//app.use(express.static(path.join(__dirname, 'Public')));
//add this middleware
app.use(express.static('./Public'));
app.use('/Style',express.static('./Public/Style'));
app.use('/Client',express.static('./Public/Client'));

Cannot POST using express and body-parser

Please can you help me out, for some reason I am not able to post and am getting a "cannot POST /api/create" and when inspecting the page a 404 error is shown.
Here is my index.js:
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var mainRouter = require('./mainRouter.js');
var todoRoutes = require('./todoRoutes.js');
//tell express to use bodyParser for JSON and URL encoded form bodies
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
//mouting our routers
app.use('/', mainRouter);
app.use('/todo',todoRoutes);
app.listen(3000);
console.log("Express server running on port 3000");
And the corresponding todoRoutes.js file is where I require the post method:
var express = require('express');
var todoRoutes = express.Router();
var todoList = []; //to do list array
todoRoutes.get('/', function(req, res) {
res.sendFile(__dirname + '/views/todo/index.html');
});
todoRoutes.get('/create', function(req, res) {
res.sendFile(__dirname + '/views/todo/create.html');
});
todoRoutes.get('/api/list', function(req, res) {
res.json(todoList); //respond with JSON
});
todoRoutes.get('/api/get/:id',function(req, res){
res.json(todoList[req.params.id]);
});
todoRoutes.post('/api/create', function(req, res){
console.log("Creating the following todo:", req.body.todo);
todoList.push(req.body.todo);
res.send({redirect: '/api/list'});
});
and here is the corresponding html file:
<!DOCTYPE html>
<html lang = "en">
<head>
<title>Todo List: Create</title>
<meta charset="utf-8" />
</head>
<body>
<form action = "/api/create" method="post">
<div>
<label for="todo">Enter your new Todo:</label>
<input type="text" id="todo" name="todo">
</div>
<div class="button">
<button type="submit">Add</button>
</div>
</form>
</body>
</html>
If I put a console.log("") in the POST function of the todoRoutes.js file it will not be displayed, indicating that the function does not even get executed.
Any help will be very much appreciated.
You need to POST to /todo/api/create, based on your current route handling:
<form action = "/todo/api/create" method="post">

Ejs rendered vars are undefined

I'm writing my first webb ap with nodejs and express, using ejs templates.
now when I'm rendering the html files it all works fine, but when I try to render the files with parameters, it seems like the rendered ejs template can't find the parameters I've sent to it.
here is my file structure :
project/
Views/
index.ejs
login.ejs
public/
all the css files ..
node_modules/
server.js
and here is my server.js :
var express = require('express');
var app = express();
const cookieParser = require('cookie-parser');
const session = require('express-session');
const bodyParser = require('body-parser')
app.set('view engine', 'ejs');
app.use(express.static(__dirname + '/Public'));
app.use(cookieParser());
app.use(session({secret: '1234567890QWERTY',resave: false, saveUninitialized: false})); // change the secret to safer one
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.get('/', function(req, res) {
if (req.session.user == undefined) {
// if user is not logged-in redirect back to login page //
res.render('login');
} else {
console.log(req.session.user);
res.render('index', {username:req.session.user});
}
});
app.get('/login', function(req, res) {
res.render('login');
});
app.listen(8080);
console.log('port: 8080');
and here is my index.ejs file:
<!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, shrink-to-fit=no">
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
<meta name="description" content="">
<meta name="author" content="">
<link rel="icon" href="../../favicon.ico">
<title>Dashboard</title>
</head>
<body>
<div><%= username %></div>
</body>
</html>
and for some reason whenever I try to access index.ejs, it returnes an error -
"username is not defined"
any idea what I'm doing wrong? the examples online looks exactly the same
thanks !
after Fadi Bitar answered this is how my server get event looks like and it's stil won't work:
app.get('/', function(req, res) {
if (req.session.user == undefined) {
// if user is not logged-in redirect back to login page //
res.render('login',{username:req.session.user});
} else {
console.log(req.session.user);
res.render('index', {username:req.session.user});
}
});
// about page
app.get('/login', function(req, res) {
res.render('login',{username:req.session.user});
});
In the initial code, it should work... Without seeing it my guess is that you are trying to echo <%=username%> in login.ejs.
Your updated code has a couple of points where you're using a variable that doesn't exist.
if (req.session.user == undefined) {
res.render('login',{username:req.session.user});
}
Here you're saying 'if req.session.user is undefined, set username to req.session.user' (undefined).
Then this bit does the same..
app.get('/login', function(req, res) {
res.render('login',{username:req.session.user});
});
I assume here that when you go to /login req.session.user is not set, so that's why that errors...
I believe you are missing the "username" variable in your get function.
Make sure you do:
res.render('/', {username: "example username"});

Resources