I am new to Node js and trying to create a blog system. When i tried to console the posted value in categories.js file, i am getting value as "undefined". I am using post.js for adding new posts and category.js for adding new categories.
Here is my app.js file.
var createError = require('http-errors');
var express = require('express');
var expressValidator = require('express-validator');
var path = require('path');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var multer = require('multer');
var upload = multer({dest: './public/images/uploads'});
var flash = require('connect-flash');
var logger = require('morgan');
var mongodb = require('mongodb');
var db = require('monk')('localhost/nodeblog');
var indexRouter = require('./routes/index');
var posts = require('./routes/posts');
var categ = require('./routes/categories');
var app = express();
app.locals.moment = require('moment');
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
// Session
app.use(session({
secret: 'secret',
resave: true,
saveUninitialized: true
}));
// Validator
app.use(expressValidator({
errorFormatter: function(param, msg, value) {
var namespace = param.split('.')
, root = namespace.shift()
, formParam = root;
while(namespace.length) {
formParam += '[' + namespace.shift() + ']';
}
return {
param: formParam,
msg: msg,
value: value
};
}
}));
// Connect Flash
app.use(require('connect-flash')());
app.use(flash());
app.use(function (req, res, next) {
res.locals.messages = require('express-messages')(req, res);
next();
});
// Make our db accessible to our router
app.use(function(req, res, next) {
req.db = db;
next();
});
app.use('/', indexRouter);
app.use('/posts', posts);
app.use('/categories', categ);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
Here is my post.js file
var express = require('express');
var router = express.Router();
var mongodb = require('mongodb');
var multer = require('multer');
var upload = multer({dest: './public/images/uploads'});
var db = require('monk')('localhost/nodeblog');
router.get('/add', function(req, res, next) {
var categories = db.get('categories');
categories.find({}, {}, function(err, categories) {
res.render('addpost', {
"title" : "Add Post",
"categories": categories
});
});
});
router.post('/add', upload.single('profileimage'), function(req, res, next) {
// Getting Form Values
var title = req.body.title;
console.log(title);
var category = req.body.category;
var body = req.body.body;
var author = req.body.author;
var date = new Date();
if(req.file) {
var profileimage = req.file.filename;
} else {
var profileimage = 'noimage.png';
}
// Form Validation
req.checkBody('title', 'Title Field is required').notEmpty();
req.checkBody('body', 'Body field is required').notEmpty();
// Check for Errors
var errors = req.validationErrors();
if(errors) {
res.render('addpost', {
"errors": errors,
"title": title,
"body": body
});
} else {
var posts = db.get('posts');
// Submitting values to DB
posts.insert({
"title": title,
"body": body,
"category": category,
"date": date,
"author": author,
"profileimage": profileimage
}, function(err, post) {
if(err) {
res.send("There is an issue in submitting the post");
} else {
req.flash('success','Post Submitted Successfully');
res.location('/');
res.redirect('/');
}
});
}
});
module.exports = router;
Here is my category file.
var express = require('express');
var router = express.Router();
router.get('/add', function(req, res, next) {
res.render('addcategory', {
"title" : "Add Category"
});
});
router.post('/add', function(req, res, next) {
// Getting Form Values
var title = req.body.title;
//console.log(req.body);
console.log(title);
});
module.exports = router;
Here is the addcategory jade file.
extends layout
block content
h1=title
ul.errors
if errors
each error, i in errors
li.alert.alert-danger #{error.msg}
form(method='post', action='/categories/add', enctype='multipart/form-data')
.form-group
label Title:
input.form-control(name='title',type='text')
input.btn.btn-default(name='submit',type='submit',value='Save')
Here is post jade file.
extends layout
block content
h1=title
ul.errors
if errors
each error, i in errors
li.alert.alert-danger #{error.msg}
form(method='post', action='/posts/add', enctype='multipart/form-data')
.form-group
label Title:
input.form-control(name='title', type='text')
.form-group
label Category
select.form-control(name='category')
each category, i in categories
option(value= '#{category.title}') #{category.title}
.form-group
label Body
textarea.form-control(name='body', id='body')
.form-group
label Main Image
input.form-control(name='profileimage', type='file')
.form-group
label Author
select.form-control(name='author')
option(value='Deepesh') Deepesh
option(value='Sudha') Sudha
input.btn.btn-default(name='submit', type='submit', value='Save')
script(src='/ckeditor/ckeditor.js')
script
| CKEDITOR.replace('body');
I am getting req.body value in post.js. But when i tried to get the same in categories.js, i am getting the value as undefined. I need to get the value of title in categories file, where the same should work in post file.
Can you guys find me a solution for the same. I tried from my end, but didn't get a proper solution.
Routing refers to determining how an application responds to a client request to a particular endpoint. you created 2 routers for the same endpoint.
router.post('/add', function(req, res, next) {} //in categories.js and post js
once you requested data, data will go to specified address and router will take it and handle it. so you are getting the request to post.js and express handles it and then responds it. so that request will be ended.
but in categories.js you are waiting for the same request which is already gone. if you wanna test it, comment out the router.post in the post.js and and you will see that express will handle the request in categories.js.
Related
I want make auth app using nodejs and got error like the title :(
but code for app.js is already like this
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var session = require('express-session')
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(session({
secret: '123456cat',
resave: false,
saveUninitialized: true,
cookie: { maxAge: 60000 }
}))
app.use(express.static(path.join(__dirname, 'public')));
var registrationRouter = require('./routes/registration-route').default;
var loginRouter = require('./routes/login-route').default;
var dashboardRouter = require('./routes/dashboard-route').default;
var logoutRouter = require('./routes/logout-route');
app.use('/', registrationRouter);
app.use('/', loginRouter);
app.use('/', dashboardRouter);
app.use('/', logoutRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
app.listen(3000);
module.exports = app;
this is registration-route.js
var express = require('express');
var router = express.Router();
var db = require('../database');
// to display registration form
router.get('/register', function(req, res, next) {
res.render('registration-form');
});
// to store user input detail on post request
router.post('/register', function(req, res, next) {
inputData ={
username: req.body.username,
email_address: req.body.email_address,
password: req.body.password,
confirm_password: req.body.confirm_password
}
// check unique email address
var sql='SELECT * FROM registration WHERE email_address =?';
db.query(sql, [inputData.email_address] ,function (err, data, fields) {
if(err) throw err
if(data.length>1){
var msg = inputData.email_address+ "was already exist";
}else if(inputData.confirm_password != inputData.password){
var msg ="Password & Confirm Password is not Matched";
}else{
// save users data into database
var sql = 'INSERT INTO registration SET ?';
query(sql, inputData, function (err, data) {
if (err) throw err;
});
var msg ="Your are successfully registered";
}
res.render('registration-form',{alertMsg:msg});
})
});
module.exports = router;
login-route.js
var express = require('express');
var router = express.Router();
var db = require('../database');
/* GET users listing. */
router.get('/login', function(req, res, next) {
res.render('login-form');
});
router.post('/login', function(req, res){
var email = req.body.email;
var password = req.body.password;
var sql='SELECT * FROM registration WHERE email_address =? AND password =?';
db.query(sql, [email, password], function (err, data, fields) {
if(err) throw err
if(data.length>0){
req.session.loggedinUser= true;
req.session.email= email;
res.redirect('/dashboard');
}else{
res.render('login-form',{alertMsg:"Your Email Address or password is wrong"});
}
})
})
module.exports = router;
logout-route.js
var express = require('express');
var router = express.Router();
/* GET users listing. */
router.get('/logout', function(req, res) {
req.session.destroy();
res.redirect('/login');
});
module.exports = router;
dashboard-route.js
var express = require('express');
var router = express.Router();
/* GET users listing. */
router.get('/dashboard', function(req, res, next) {
if(req.session.loggedinUser){
res.render('dashboard',{email:req.session.emailAddress})
}else{
res.redirect('/login');
}
});
module.exports = router;
I already see questions like this but none of the answers are working for my case problem
also I'd tried to npm clear cache --force but nothing changed
also had been uninstalled and reinstalled for node_modules , package-lock but always got same error
Change all of these:
var registrationRouter = require('./routes/registration-route').default;
to remove the .default so you just have this:
const registrationRouter = require('./routes/registration-route');
.default is something that is used with ESM modules, not with CommonJS modules.
Also, you shouldn't be using var any more. It's obsolute now. Use const for these.
I'm very new and following a Udemy course for node/express/mongo however I've run into a snag that I can't sort out. I'm using express-validator in my form code and can't get past this error. I suspect there is some error in the way I am using express-validator.
In users.js
var express = require('express');
var router = express.Router();
var multer = require('multer');
var upload = multer({dest: './uploads'});
/* GET users listing. */
router.get('/', function(req, res, next) {
res.send('respond with a resource');
});
// Register Page
router.get('/register', function(req, res, next) {
res.render('register', { title: 'Register Page'})
});
// Login Page
router.get('/login', function(req, res, next) {
res.render('login', { title: 'Login Page'})
});
router.post('/register', upload.single('profileimage'), function(req, res, next) {
var name = req.body.name;
var email = req.body.email;
var username = req.body.username;
var password = req.body.password;
var password2 = req.body.password2;
if(req.file){
console.log('Uploading Picture file...')
var profileimage = req.file.filename;
} else {
console.log('No file uploaded');
var profileimage = 'noimage.jpg';
}
// Form Validator
req.checkBody('name', 'Name field is required').notEmpty();
req.checkBody('email', 'Email field is required').notEmpty();
req.checkBody('email', 'Email is not valid').isEmail();
req.checkBody('username', 'Username field is required').notEmpty();
req.checkBody('password', 'Password field is required').notEmpty();
req.checkBody('password2', 'Passwords do not match.').equals(req.body.password);
// Check Errors
app.use(expressValidator({
errorFormatter: function(param, msg, value) {
var namespace = param.split('.')
, root = namespace.shift()
, formParam = root;
while(namespace.length) {
formParam += '[' + namespace.shift() + ']';
}
return {
param : formParam,
msg : msg,
value : value
};
}
}));
if(errors){
res.render('register', {
errors: errors
});
} else {
console.log('No Errors')
}
});
module.exports = router;
In 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 session = require('express-session');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var expressValidator = require('express-validator');
var multer = require('multer');
var upload = multer({dest: './uploads'});
var flash = require('connect-flash');
//var bcrypt = require('bcryptjs');
var mongo = require('mongodb');
var mongoose = require('mongoose');
var db = mongoose.connection;
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(session({
secret:'secret',
saveUninitialized: true,
resave: true
}));
// Passport
app.use(passport.initialize());
app.use(passport.session());
// Validator
app.use(expressValidator())
app.use('/', indexRouter);
app.use('/users', usersRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
In register.pug
extends layout
block content
h2.page-header Register
p Please register using the form below
form(action="/users/register", method="post", enctype='multipart/form-data')
.form-group
label Name
input.form-control(name='name', type='text', placeholder='Enter Name')
.form-group
label Email
input.form-control(name='email', type='text', placeholder='Email')
.form-group
label Username
input.form-control(name='username', type='text', placeholder='Username')
.form-group
label Password
input.form-control(name='password', type='password', placeholder='Password')
.form-group
label Confirm Password
input.form-control(name='password2', type='password', placeholder=' Confirm Password')
.form-group
label Profile Image
input.form-control(name='profileimage', type='file')
input.btn.btn-primary(type='submit', name='submit', value='Submit')
Thank you for all your help!
I think express validator chnaged their documentation and github page that ou dont have to use longer middleware. https://express-validator.github.io/docs/5.3.0/index.html
// Check Errors
app.use(expressValidator({
errorFormatter: function(param, msg, value) {
var namespace = param.split('.')
, root = namespace.shift()
, formParam = root;
while(namespace.length) {
formParam += '[' + namespace.shift() + ']';
}
return {
param : formParam,
msg : msg,
value : value
};
}
}));
I am not sure if it is about that but. Just try
const { check, validationResult } = require('express-validator'); instead of it
Actually I am not a professional but I just want to help you. If it is wrong we will research and do it untill we achieve.
I am trying to make a form in Node.js using Express by following a tutorial. I am writing the validation logic which should show error messages if the form
gets submitted empty, however instead of doing that it gives me this error on line 33 and I can't figure out why:
Cannot read property 'profileimage' of undefined
I debugged it but couldn't figure out what is causing this.
What am I doing wrong, how can I fix it?
Here is the form code:
var express = require('express');
var router = express.Router();
/* GET users listing. */
router.get('/', function(req, res, next) {
res.send('respond with a resource');
});
router.get('/register', function(req, res, next) {
res.render('register', {
'title': 'Register'
});
});
router.get('/login', function(req, res, next) {
res.render('login', {
'title': 'Log In'
});
});
router.post('/register', function(req, res, next) {
var name = req.body.name;
var email = req.body.email;
var username = req.body.username;
var password = req.body.password;
var password2 = req.body.password2;
// Check for Image Field
if(req.files.profileimage){
console.log('uploading File...');
// File Info
var profileImageOriginalName = req.files.profileimage.originalname;
var profileImageName = req.files.profileimage.name;
var profileImageMime = req.files.profileimage.mimetype;
var profileImagePath = req.files.profileimage.path;
var profileImageExt = req.files.profileimage.extension;
var profileImageSize = req.files.profileimage.size;
} else {
// Set a Default Image
var profileImageName = 'noimage.png';
}
// Form Validation
req.checkBody('name','Name field is required').notEmpty();
req.checkBody('email','Email field is required').notEmpty();
req.checkBody('email','Email not valid').isEmail();
req.checkBody('username','Username field is required').notEmpty();
req.checkBody('password','Password field is required').notEmpty();
req.checkBody('password2','Password do not match').equals(req.body.password);
// Check for errors
var errors = req.validationErrors();
if(errors){
res.render('register', {
errors: errors,
name: name,
email: email,
username: username,
password: password,
password2: password2
});
} else {
var newUser = new User({
name: name,
email: email,
username: username,
password: password,
profileImage: profileImageName
});
// Create User
User.createUser(newUser, function(err, user){
if(err)throw err;
console.log(user);
});
//Success Message
req.flash('success', 'You are now registered and may log in');
res.location('/');
res.redirect('/');
}
});
module.exports = router;
and my app.js:
var express = require('express');
var path = require('path');
var logger = require('morgan');
var expressValidator = require('express-validator');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var bodyParser = require('body-parser');
var multer = require('multer');
var flash = require('connect-flash');
var mongo = require('mongodb');
var mongoose = require('mongoose');
var db = mongoose.connection;
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');
// Handle file uploads
var multer = require('multer');
var upload = multer({ dest: './uploads' });
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
// Handle Express Sessions
app.use(session({
secret:'secret',
saveUninitialized: true,
resave: true
}));
// passport
app.use(passport.initialize());
app.use(passport.session());
// Validator
app.use(expressValidator({
errorFormatter: function(param, msg, value) {
var namespace = param.split('.')
, root = namespace.shift()
, formParam = root;
while(namespace.length) {
formParam += '[' + namespace.shift() + ']';
}
return {
param : formParam,
msg : msg,
value : value
};
}
}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(flash());
app.use(function (req, res, next) {
res.locals.messages = require('express-messages')(req, res);
next();
});
app.get('*', function(req, res, next){
res.locals.user = req.user || null;
next();
});
app.use('/', routes);
app.use('/users', users);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
First of all files should be an array. If you are sure you send only one file try with this code block:
// Check for Image Field
if(req.files && req.files[0] && req.files[0].profileimage){
console.log('uploading File...');
// File Info
var profileImageOriginalName = req.files[0].profileimage.originalname;
var profileImageName = req.files[0].profileimage.name;
var profileImageMime = req.files[0].profileimage.mimetype;
var profileImagePath = req.files[0].profileimage.path;
var profileImageExt = req.files[0].profileimage.extension;
var profileImageSize = req.files[0].profileimage.size;
} else {
// Set a Default Image
var profileImageName = 'noimage.png';
}
You have the following line in your code:
if(req.files.profileimage){
when files is undefined, meaning, req does not have the property files (maybe a file was not sent on this request?), then trying to access anything within it will throw an error (and crash your node if you don't catch it)
So, first you should add type safety like so:
if(req.files && req.files.profileimage) {
or, even stricter, like so:
if(typeof req.files === 'object' && req.files.profileimage) {
(Note: you should do type safety test if and only if another part of your code has not already guaranteed that it is safe, e.g. a previous type safety test, or you assigned the property explicitly yourself in the code)
I also see that you are using multer to get a files object in your req object. Accroding to its docs, files can be an array, or an object of strings to arrays, From the "multer" npm page:
If used like so:
app.post('/photos/upload', upload.array('photos', 12), function (req, res, next) {
It will be an array:
req.files is array of photos files
req.body will contain the text fields, if there were any
Or, if used like so:
var cpUpload = upload.fields([{ name: 'avatar', maxCount: 1 }, { name: 'gallery', maxCount: 8 }])
app.post('/cool-profile', cpUpload, function (req, res, next) {
then it will be a (String -> Array) object:
req.files is an object (String -> Array) where fieldname is the key, and the value is array of files
e.g.
req.files['avatar'][0] -> File
req.files['gallery'] -> Array
So you should change your code accordingly. For example, if you choose the second method, you should change to the following:
if(typeof req.files === 'object' && req.files.profileimage) {
req.files.profileimage.forEach((profileimage) => {
//do anything you previously did on req.files.profileimage, on profileimage
let profileImageMime = profileimage.mimetype;
//... more things and code...
})
}
I am trying to wrap my head around defining and using an API in Express, using Mongoose to hook up with MongoDB. So far I am saving objects just fine form input on the front end. However, I seem to be lost when it comes down to retrieving and displaying the data I've saved.
Here is some code:
db.js:
const mongoose = require('mongoose');
//mongoose setup
mongoose.connect(mongooseUrl, { useNewUrlParser: true });
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {
console.log('mongoose connected to ' + mongooseUrl);
});
module.exports = db;
app.js:
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
// import routers
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var apiRouter = require('./routes/api');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hbs');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/api', apiRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
/routes/api.js:
var express = require('express');
var mongoose = require('mongoose');
var db = require('../config/db.js');
var Kitten = require('../models/kitten.js');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('api', {
title: 'Test API',
content: 'you\'re in the right place',
buttontext: 'send POST request'
});
});
router.post('/newKitten', function(req, res, next) {
var kitty = new Kitten({
name: req.body.name,
color: req.body.color
});
console.log("new kitty: " + kitty.name + " color: " + kitty.color );
kitty.save().then(console.log(kitty + " was saved to the database"));
res.send('new: ' + kitty);
});
router.get('/kittens', function (req, res, next) {
var kittens = Kitten.find({}, 'name color');
res.render('kittens', {title: 'Kittens', list_kittens: kittens });
});
module.exports = router;
models/kitten.js
const mongoose = require('mongoose');
var Schema = mongoose.Schema;
var kittenSchema = new Schema({
name: String,
color: String
});
var Kitten = mongoose.model("Kitten", kittenSchema);
module.exports = Kitten;
views/kitten.hbs:
<h1>{{title}}</h1>
<ul>
{{#each list_kittens as |kitten|}}
<li>name: {{kitten.name}}, color: {{kitten.color}}</li>
{{/each}}
</ul>
Now with all that laid out, when I visit http://localhost:3000/api/kittens this is what I see:
The kittens are stored in MongoDB, proof:
I have no idea why this is not rendering the kittens I have saved in my MongoDB database... The data is there, but I seem to be confused about how mongoose is supposed to be querying the data. Any and all help is appreciated. I've been stuck on this for a few days.
Model.find returns a promise. You have to add a function then to get the kittens and render them:
Kitten.find(...)
.then(kittens => {
res.render(...)
})
EDIT
Based on #Francisco Mateo comment, Kitten.find returns a Query you can execute with exec. Here is the code:
Kitten.find(...).exec()
.then(kittens => {
res.render(...)
})
In routes/api.js
var express = require('express');
var mongoose = require('mongoose');
var db = require('../config/db.js');
var Kitten = require('../models/kitten.js');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('api', {
title: 'Test API',
content: 'you\'re in the right place',
buttontext: 'send POST request'
});
});
router.post('/newKitten', function(req, res, next) {
var kitty = new Kitten({
name: req.body.name,
color: req.body.color
});
console.log("new kitty: " + kitty.name + " color: " + kitty.color );
kitty.save().then(console.log(kitty + " was saved to the database"));
res.send('new: ' + kitty);
});
router.get('/kittens', async function (req, res, next) { **//Change here**
var kittens = await Kitten.find({}, 'name color'); **//change here**
res.render('kittens', {title: 'Kittens', list_kittens: kittens });
});
module.exports = router;
The Kitten.find({}, 'name color') is returning a promise , so you have to wait until the data is returned.
Jade is not an easy language to deal with because of the proper indentation and what not, but in this case indentation does not seem to be the problem and I have Google-Foo'd the error and cannot find one that matches what is going on here.
This is my addpost.jade file:
extends layout
block content
h1=title
ul.errors
if errors
each error, i in errors
li.alert.alert-danger #{error.msg}
form(method='post', action='/posts/add', enctype="multipart/form-data")
.form-group
label Title:
input.form-control(name='title', type='text')
.form-group
label Category
select.form-control(name='category')
each category, i in categories
option(value='#{category.title}') #{category.title}
.form-group
label Body
textarea.form-control(name='body', id='body')
.form-group
label Main Image:
input.form-control(name='mainimage', type='file')
.form-group
label Author
select.form-control(name='author')
option(value='Daniel Cortes') Daniel Cortes
option(value='Alejandra Rocha') Alejandra Rocha
input.btn.btn-default(name='submit', type='submit', value='Save')
And this is the error I am getting:
addpost.jade:16 14| label Category 15| select.form-control(name='category') > 16| each category, i in categories 17| option(value='#{category.title}') #{category.title} 18| .form-group 19| label Body Cannot read property 'length' of undefined
This is my posts.js file:
var express = require('express');
var router = express.Router();
var mongo = require('mongodb');
var db = require('monk')('localhost/nodeblog');
router.get('/add', function(req, res, next){
var categories = db.get('categories');
categories.find({},{},function(err, categories){
res.render('addpost',{
"title": "Add Post",
"categories": categories
});
});
});
router.post('/add', function(req, res, next){
// Get Form Values
var title = req.body.title;
var category = req.body.category;
var body = req.body.body;
var author = req.body.author;
var date = new Date();
if(req.files.mainimage){
var mainImageOriginalName = req.files.mainimage.originalname;
var mainImageName = req.files.mainimage.name;
var mainImageMime = req.files.mainimage.mimetype;
var mainImagePath = req.files.mainimage.path;
var mainImageExt = req.files.mainimage.extension;
var mainImageSize = req.files.mainimage.size;
} else {
var mainImageName = 'noimage.png';
}
// Form Validation
req.checkBody('title','Title field is required').notEmpty();
req.checkBody('body', 'Body field is required');
// Check errors
var errors = req.validationErrors();
if(errors){
res.render('addpost',{
"errors": errors,
"title": title,
"body": body
});
} else {
var posts = db.get('posts');
// Submit to db
posts.insert({
"title": title,
"body": body,
"category": category,
"date": date,
"author": author,
"mainimage": mainimage
}, function(err, post){
if(err){
res.send('There was an issue submitting the post');
} else {
req.flash('success','Post Submitted');
res.location('/');
res.redirect('/');
}
});
}
});
module.exports = router;
my app.js file:
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var expressValidator = require('express-validator');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var bodyParser = require('body-parser');
var mongo = require('mongodb');
var db = require('monk')('localhost/nodeblog');
var multer = require('multer');
var flash = require('connect-flash');
var routes = require('./routes/index');
var posts = require('./routes/posts');
var app = express();
app.locals.moment = require('moment');
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// Handle File Uploads & Multipart Data
// app.use(multer({dest: './uploads'}));
app.use(multer({dest:'./uploads/'}).single('singleInputFileName'));
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
// Express Session
app.use(session({
secret: 'secret',
saveUninitialized: true,
resave: true
}));
// Express Validator
app.use(expressValidator({
errorFormatter: function(param, msg, value){
var namespace = param.split('.'),
root = namespace.shift(),
formParam = root;
while(namespace.length) {
formParam += '[' + namespace.shift() + ']';
}
return {
param : formParam,
msg : msg,
value : value
};
}
}));
app.use(express.static(path.join(__dirname, 'public')));
// Connect Flash
app.use(flash());
app.use(function (req, res, next) {
res.locals.messages = require('express-messages')(req, res);
next();
});
// Make our db accessible to our router
app.use(function(req, res, next){
req.db = db;
next();
});
app.use('/', routes);
app.use('/posts', posts);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
It seems that the categories is not passed to the view or its not a array.
Can you add the code that render the template? May be we can find the problem there.