I'm trying to make a discussion-based Node.js/Express-app and I'm working on the page to create a discussion. I was just testing if my discussion controller file was linked, but everytime I click the button to POST my form, it doesn't do anything.
my pug (view), called 'createDisc.pug'
extends layout
block content
h1 Create new discussion
form(action='', method='post')
div
label(for='title') Title
input#title
div
label(for='desc') Description
input#desc
div
input(type='submit', value='Create')
my router, called 'createDisc.js'
var express = require('express');
var router = express.Router();
var disc = require('../controllers/disc');
router.get('/discussion/create', function (req, res, next) {
res.render('createDisc');
});
router.post('/discussion/create', disc.createDisc);
module.exports = router;
my controller called 'disc.js' where I'm just trying to send 'test' to my console
exports.createDisc = function (req, res, next) {
console.log('test');
};
my app.js file
const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const passport = require('passport');
const path = require('path');
const cookieParser = require('cookie-parser');
const session = require('express-session');
const app = express();
const db = require('./controllers/db');
require('./config/passport')(passport);
mongoose.connect(db.url);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(bodyParser.json());
app.use(express.static(path.join(__dirname, 'public')));
app.use(bodyParser.urlencoded({extended: true}));
app.use(cookieParser());
app.use('/', require('./routes/createDisc'));
app.listen(3000, function() {
console.log('Example listening on port 3000!')
})
You mentioned /discussion/create as your GET route and linking it to the express router like:
router.get('/discussion/create', function (req, res, next) {
res.render('createDisc');
});
router.route('/discussion/create', disc.createDisc);
So in reality, you are enabling the route something like:
GET /discussion/create/discussion/create
Please try with .post() hook and use it like:
router.post('/', function (req, res, next) {
res.render('createDisc');
});
router.route('/discussion', disc.createDisc);
Reference: http://expressjs.com/en/guide/routing.html
Tip: Please refer to this link for making more meaningful routes. https://github.com/squareboat/api-guidelines#http-methods
Update #1
Currently, in your HTML(pug) form, you have action='', this means your form is making request to POST /.
Please change the action value to action='/discussion/create' and try again.
Update #2
I have made a trimmed down version of your code(without view or db), and it's working perfectly. you can see code here.
Routes to test are:
GET http://localhost:3000/discussion/create
POST http://localhost:3000/discussion/create
Update #3
In your pug file, your indentation is wrong because of which the input fields are not enclosed inside the form tag. You had an empty form.
extends layout
block content
h1 Create new discussion
form(action='/discussion/create', method='post')
div
label(for='title') Title
input#title
div
label(for='desc') Description
input#desc
div
input(type='submit', value='Create')
This will work.
Try to modify the form to be like this :
form(method='post', action='./create')
And see if it works
Related
In my router code, I have something like below. In my main page, I have a button to jump to login page, that is work with out nodejs, but after I connect the node.js code, only show me the main page, if I click the login button, the page will show be that Cannot GET /LoginPage.html. How to fix that?
const express = require('express')
const router = express.Router()
router.get('/', (req, res) => {
res.render('HomePage.html', {
title: 'Hello World'
})
})
router.get('/login', (req, res) => {
res.render('LoginPage.html', {
title: 'Hello World'
})
})
In the app.js code:
const passport = require('passport')
const flash = require('express-flash')
const session = require('express-session')
const multer = require('multer');
const GridFsStorage = require("multer-gridfs-storage");
const path = require('path')
const cors = require('cors')
const crypto = require("crypto");
const favicon = require('serve-favicon')
const app = express();
const User = require('./models/user')
const router = require('./router')
app.engine('html', require( 'express-art-template'))
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.use(express.static(__dirname + '/public'))
app.use('/node_modules/', express.static(__dirname + '/node_modules'))
app.use(cors());
app.use(router)
app.listen(4001, (req, res) => {
console.log('port xxxx')
})
In the HTML code, just click the button, and jump to Loginpage.html
Login
A couple of things,
you have 2 same endpoints router.get('/',
So change the second route to something like router.get('/login',
you should access your login page now on /login
You are getting Cannot GET /LoginPage.html because there is no route LoginPage.html in your backend
First thing is the way you defined the routes is wrong as you have 2 same end points.Try to change the login endpoint as /login in your .js file.
You need to change the html file also as you are trying to call directly the html file not the api end point /login.You need to call to the node backend endpoint which renders the desired html file.
not the direct reference to html file.
Edit 1:
Please do the following:
Change your app.js file like below:
const express = require('express');
const app = express();
const router = require('./router');
const bodyParser = require('body-parser');
const path = require('path');
const cors = require('cors');
app.engine('html', require('express-art-template'));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use('', express.static(path.join(__dirname, 'public')));
app.use(cors());
app.use(router);
app.listen(4001, (req, res) => {
console.log('port 4001');
});
And the router.js to like this
const express = require('express');
const router = express.Router();
router.get('/', (req, res) => {
res.render('index.html', {
title: 'Hello World',
});
});
router.get('/login', (req, res) => {
res.render('login.html', {
title: 'Hello World',
});
});
module.exports = router;
And create a public folder and create 2 html files index.html and login.html. Your app structure should be like below:
--public
-------+ index.html
-------+ login.html
-- app.js
--router.js
--package.json
I tried this it worked for me. Change the variables and other file names as per your need. I guess your folder structure and the way you are rendering is wrong.Hopefully it should work.
I dont know why did? Help me debug! Please
i try console.log(req.body) and i get {} (empty object)
I tried many ways but I still couldn't understand why.
I tried using middleware but it didn't work either
const express = require("express");
const app = express();
const pug = require('pug');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.set('view engine' , 'pug');
app.set('views', './views');
const low = require('lowdb')
const FileSync = require('lowdb/adapters/FileSync')
const adapter = new FileSync('./db.json')
const db = low(adapter)
app.get('/todos/create', (req, res)=> {
res.render('create');
});
app.post('/todos/create', (req,res)=> {
console.log(req.body);
db.get('todos').push(req.body).write();
res.redirect('/todos');
});
app.listen(3000);```
this is file create.bug
```h1 Create New List
form(action="/todos/create", method="post", enctype="multipart/form-data")
.form-group
label(for="id") Id
input#id(name="id" type="text")
.form-group
label(for="text") Text
input#text(name="text" type="text")
button Create```
----------
The body-parser module is responsible for parsing data ; you use it in your code, but I don't even see where you import it. You need at least to import it at the top of your file
var bodyParser = require('body-parser')
See others example of use here : https://www.npmjs.com/package/body-parser
I'm having some trouble accessing request parameters in express router.
My server.js file has this:
app.use('/user/:id/profile', require('./routes/profile');
And this is in my ./routes/profile.js file:
router.get('/', (req, res) => {
console.log(req.params.id);
}
But the console log prints undefined.
I'm new to express and feel like I'm missing something basic about how routing works.
Can someone please help me out?
Here is my full server.js:
const express = require('express');
const app = express();
app.use(express.json());
app.use('/user/:id/profile', require('./routes/profile'));
app.listen(5000, () => console.log('Listening'));
Here is my full profile.js:
const express = require('express');
const router = express.Router();
router.get('/', (req, res) => {
console.log(req.params.id);
res.status(200).send('In profile route');
});
module.exports = router;
URL parameters are not exposed to routers. You have a couple of options here:
Parse req.originalUrl to get the user id (not recommended). req.originalUrl isn't affected by the router's mount point and will remain as /user/112/profile or whatever url you visited.
Add some middleware to expose the id (recommended). Your new route statement will end up looking like this:
(Now you can use req.userId in your profile.js)
app.use('/user/:id/profile', function(req, res, next) {
req.userId = req.params.id;
next();
}, require('./routes/profile'));
Change the mount point from /user/:id/profile to /user, then edit your router to listen on /:id/profile (not recommended).
app.js
var express = require("express");
var app = express();
var path = require('path');
var db = require('./db');
var bodyParser = require('body-parser');
app.listen(80);
app.set('view engine', 'jade');
app.set('views', "./views");
// app.get('/', _GetMainPage);
// app.get('/sites', _GetSites);
app.use(express.static(path.join(__dirname, 'public')));
app.use(bodyParser.urlencoded({ extended: true })); // Support encoded bodies
app.use(bodyParser.json()); // Support json encoded bodies
app.use(require('./controllers'));
./controllers/index.js
var express = require('express');
var router = express.Router();
router.use('/', require('./sites'));
router.use('/site', require('./site'));
module.exports = router;
./controllers/sites.js
var express = require('express');
var router = express.Router();
var site = require('../models/site');
router.get('/', function(req, res) {
site.getAll(function(err, rows){
if(err) {
res.send(err);
return;
}
res.render('sites', { sites : rows });
});
});
./controllers/site.js
var express = require('express');
var router = express.Router();
var site = require('../models/site');
router.get('/site', function(req, res) {
// console.log("get /site received. req.body: " + req.body);
res.render('site', {
site: {
name : req.params.name
}
});
});
module.exports = router;
When I request localhost/site I get a response saying:
Cannot GET /site
localhost/ works perfectly
I have been looking at this for a while and can't find the problem yet. If there is anything I can add, let me know. Thanks.
Thank you to the person that commented with the answer:
What happens if you navigate to /site/site? Your site.js route is relative to the route you provided in use. So it should be router.get('/' ... not router.get('/site' ...
The ./controllers/site route is already being routed to /site. On top of this I was calling router.get('/site', ...). This means it was actually routing to /site/site.
The solution is to just use router.get('/', ...) in the site.js file instead.
This really helped me, thank you.
Basically, the root path in the sub-app is defined in your core app where you mount it via the app.use() method.
the best example I can find from app.mountpath docs is here:
https://expressjs.com/en/4x/api.html#express.router
The app.mountpath property contains one or more path patterns on which a sub-app was mounted.
var express = require('express');
var app = express(); // the main app
var admin = express(); // the sub app
admin.get('/', function (req, res) {
console.log(admin.mountpath); // /admin
res.send('Admin Homepage');
});
app.use('/admin', admin); // mount the sub app
It is similar to the baseUrl property of the req object, except
req.baseUrl returns the matched URL path, instead of the matched
patterns.
If a sub-app is mounted on multiple path patterns, app.mountpath
returns the list of patterns it is mounted on, as shown in the
following example.
var admin = express();
admin.get('/', function (req, res) {
console.log(admin.mountpath); // [ '/adm*n', '/manager' ]
res.send('Admin Homepage');
});
var secret = express();
secret.get('/', function (req, res) {
console.log(secret.mountpath); // /secr*t
res.send('Admin Secret');
});
admin.use('/secr*t', secret); // load the 'secret' router on '/secr*t', on the 'admin' sub app
app.use(['/adm*n', '/manager'], admin); // load the 'admin' router on '/adm*n' and '/manager', on the parent app
I am finding a trouble to set a session with node.js using express4.2.0 I show you my code and after I comment:
APP.js
var express = require('express');
var path = require('path');
var favicon = require('static-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var cookieSession = require('cookie-session');
var mainModel = require('./model/main_model');
var users = require('./routes/users');
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(favicon());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(cookieSession({
keys: ['secret1', 'secret2']
}));
app.use('/users', users);
/*Evething that express makes automatically*/
app.listen(8080);
USERS.js
var express = require('express');
var router = express.Router();
router.get('/', function(req, res)
{
if(req.cookie && req.cookie.user) res.send("COOKIE");
else if(req.session && req.session.user) res.send("SESSION");
else res.render('users/new_user', {title:"NEW USER"});
});
/*there is more content... but not relevant. */
function makeTheUserSession(result, res)
{
result['go'] = '/users';
//res.session.user = result.result[0];
//res.cookie('user', result.result[0]);
res.send(result);
}
The function makeTheUserSession is call from the method post of '/users' (to find a users on the data base).
If I uncomment the res.session.user line, when I invoque makeTheUserSession the app breaks, stop, capito, dead (Cannot set property 'user' of undefined)...
If I uncomment the res.cookie('user', result... line, when I invke the function, and after I see the browser cookies on the settings I found a cookie called user with the values of result.result[0]... but after on the get method it doesn´t works how I expect... res never sends me "COOKIE".
I had sawn the same question many times repeated, but I didn´t see a answer that worth for me: some ones talk about connect middleware (I am using express), other say to use "app.use(express.session(keyword)) but it only works with the old version of express. The express-session module is deprecated, and I would want to use a more actuallity middleware.
I hope your answers. Thank you very much.
It's req.session not res.session, fix that and you should be good to go.