I've created a very simple blog web app with ExpressJS and MongoDB. But the index page doesn't render the 'blogPosts' that I input into the DB. It only shows the title as "BL's Blog", without any posts below.
Why aren't the posts showing?
app.js:
//Module dependencies
var express = require('express');
var routes = require('./routes');
var user = require('./routes/user');
var http = require('http');
var path = require('path');
//Mongodb
var mongo = require('mongodb');
var monk = require('monk');
var db = monk('localhost:27017/hello-express/');
var app = express();
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
//GET
app.get('/', routes.index(db));
app.get('/users', user.list);
app.get('/userlist', routes.userlist(db));
app.get('/newuser', routes.newuser);
//POST
app.post('/adduser', routes.adduser(db));
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
routes/index.js(I only included exports.index as it's the relevant route to this problem):
exports.index = function(db) {
return function(req, res) {
var posts = db.get('blogPosts');
posts.find({}, {}, function(e, docs) {
res.render('index', {
"index": docs
});
});
};
};
views/index.jade:
extends layout
block content
h1.
BL's Blog
ul
- each post in index
li
h3 = post.title
p = post.content
Ok now I have actually found out the answer to my own question, thanks to the help of WiredPrairie.
The first problem lies with the name of the database that I'm using. Thus in my index.js, it should have been:
exports.index = function(db) {
return function(req, res) {
var posts = db.get('hello-express'); //Here's the difference.
posts.find({}, {}, function(e, docs) {
res.render('index', {
"index": docs
});
});
};
};
I listed in app.js that I'm using the database called 'hello-express' with this line below:
var db = monk('localhost:27017/hello-express/');
Hence the name of database being used should be named as 'hello-express'.
However, even after doing so, I could not render the Jade page properly. This was due to a syntax error (I know, I'm new.)
extends layout
block content
h1.
BL's Blog
ul
- each post in index
li
h3 #{post.title}
p #{post.content}
By using #{<var>} instead of =, the page was able to render properly. I still have no idea why this is the case, but at least it has solved my problem for now.
Related
I am using EJS for templating, when I add this
app.use("view engine","ejs")
in my code i get error.
router .use() requires a middleware function but got a string
The rest of the code:
const express = require('express');
const bodyParser = require('body-parser');
const port = 3000;
const app=express();
app.use("view engine","ejs");
app.get('/', function(req, res){
var today = new Date();
var currentDay = today.getDay();
var day ="";
if(currentDay === 6 || currentDay === 0){
day ="weekend";
}else{
day = "weekday";
}
res.render("list",{kindOfDay:day});
});
app.listen(port, function(){
console.log('The server has started');
});
Look at the documentation for using template engines:
app.set('view engine', 'pug')
use is used to add middleware, and a string isn't middleware, hence the error message.
You need to use set to set a setting.
I am at the early stages of a simple tasks manager that I want to build with the MEAN Stack.
I can figure/resolve a simple routing issue. I don't see any error message in the terminal or console except for the 404 client error.
the root path is ok. I get a response back
I use html docs to render the ui for both.
this is how I have set up my server.js
var express = require('express')
var path = require('path')
var bodyParser = require('body-parser')
var index = require('./routes/index');
var tasks = require('./routes/tasks');
var app = express();
const port = '3456'
app.use('/', index)
app.use('api', tasks) <= HERE
//view engine
app.set('views', path.join(__dirname, 'views'))
app.set('view engine', 'ejs')
app.engine('html', require('ejs').renderFile);
//static folder
app.use(express.static(path.join(__dirname, 'client')))
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended: false}))
app.listen(port, function() {
console.log('Starting the server at port' + port );
})
tasks.js
to render the template at the set route
var express = require('express')
var router = express.Router();
var mongojs = require('mongojs');
var db = mongojs('mongodb://sandy:cookie2080#ds147304.mlab.com:47304/tasklists_21092017', ['tasks'])
router.get('/tasks', function(req, res, next) {
res.send('api')
res.render('tasks.html')
db.tasks.find(function(err, tasks){
if (err) {
res.send('error message ' + err)
}
res.json(tasks)
})
})
module.exports = router;
and, index.js fyi
var express = require('express')
var router = express.Router();
router.get('/', function(req, res, next) {
res.render('index.html')
})
module.exports = router;
screenshot at the link below of the 404 error in browser after starting server on port 3456
404 error - screenshot
thanks for the help. I am sure it can be a little detail. it is very hard to debug though.
This error occurs because there's no route that handles the endpoint /api. What you can do here is create a middleware that will handle the /api. You can do it in your tasks.js like this:
tasks.js
router.get('/', function(req, res, next) {
res.send('This is api.')
})
Or if what you want to do is to direct the user from the endpoint /api to /api/tasks then you could do it like this:
router.get('/', function(req, res, next) {
res.redirect('/api/tasks')
})
Hope this helps.
I changed the port number. The issue was that the port 3000, was not responding to the requests, as it was still in use by an older process hence producing the warning
errno: 'EADDRINUSE',.
Just used the port 5000 to try out and it went through smoothly.
By the way I am using vs code.
I am currently doing a React, Express, Massivejs, postgreSql app. I am getting the error "TypeError: db.createList is not a function" anytime I'm trying to hit my post endpoint. I'm not sure how to remedy it since it looks correct.
My file structure:
My server file looks like this:
var express = require('express');
var bodyParser = require('body-parser');
var cors = require('cors');
var massive = require("massive");
var connectionString = 'postgress://LonnieMcGill#localhost/todo';
var massiveInstance = massive.connectSync({connectionString : connectionString})
var config = require('./config.js');
var app = module.exports = express();
app.set('db', massiveInstance);
var listCtrl = require('./controller/listCtrl.js');
// **************** Middleware ****************
app.use(express.static(__dirname + './../public'));
app.use(bodyParser.json());
// ****************** Endpoints ***************
app.post('/api/add/list', listCtrl.createList);
app.get('/api/get/list', listCtrl.createList);
app.get('*', function(req, res) {
res.sendFile('index.html', { root: './public'});
})
app.listen(config.port, function() { console.log('Server initiated on port', config.port); });
My controller looks like this:
var app = require('../server.js');
var db = app.get('db');
module.exports = {
createList: function(req, res, next) {
console.log('db'my);
db.createList([req.body.name], function(err, res) {
res.status(200).send('List created');
})
},
readList: function(req, res) {
db.readList(function(err, res) {
if (err) {
console.log("readList failed");
} else {
console.log("readList working " + req.body, req.params);
}
})
}
}
My createList.sql file looks like this:
INSERT INTO list (
name
)
VALUES (
$1
);
The documentation clarifies this issue. By default, the "db" folder should stay in the root directory of your project, and not where the scripts consuming the database are (in this case, "server/").
You must either move "db" to the root directory of your project (so as to be alongside "server", "public", etc.), or configure the scripts property to point to that location:
var massiveInstance = massive.connectSync({
scripts: "server/db",
connectionString
})
Struggling to get my head around this for a week and a half, I was wondering how to get a .json endpoint that is from a query from the Sequelize ORM. Currently it logs a 404 error "GET /api/users 404 3ms". As you may have heard the documentation for Sequelize is pretty limited and I've been searching github repo after tutorial and none have worked thus far, so I'd thought I'd ask here.
A small excerpt (code on https://github.com/NatuMyers/A.M.E.N.SQL-Stack):
// VARS -----------------------------
var express = require('express')
, bodyParser = require('body-parser')
, errorHandler = require('errorhandler')
, methodOverride = require('method-override')
, morgan = require('morgan')
, http = require('http')
, path = require('path')
, db = require('./models')
var router = require('express').Router();
var app = express()
// all environments
app.set('port', process.env.PORT || 3000)
app.set('views', __dirname + '/views')
app.set('view engine', 'jade')
app.use(morgan('dev'))
app.use(bodyParser())
app.use(methodOverride())
app.use(express.static(path.join(__dirname, 'public')))
// SEQUELIZE MODELS
var userVar = require('./models/user');
// dev only
if ('development' === app.get('env')) {
app.use(errorHandler())
}
// Make db, and make it listen
db
.sequelize
.sync()
.complete(function(err) {
if (err) {
throw err
} else {
http.createServer(app).listen(app.get('port'), function() {
console.log('Express server listening on port ' + app.get('port'))
})
}
})
// HTTP GET endpoints
module.exports = function() {
router.get('/', function(req, res, next){
res.json({ message: 'This works at localhost:3000/api but getting a list of users is a pain :(' });
});
// question
router.get('/users', function(req, res, next){
res.json(/* I need to make sequelize send a part of the User db here. */);
});
return router;
};
I moved on from this by using Epilogue.js (in a vanilla way).
I added models INLINE with Sequelize (I wasted lots of time trying to import models), then add any middle ware and create the restful api based on the syntax below.
// 1. ADD SEQUELIZE MODELS ---- ---- ---- ----
var database = new Sequelize('raptroopdb', 'root', 'strongpassword');
var Employee = database.define('Employee', {
name: Sequelize.STRING,
hireDate: Sequelize.DATE
});
// Add Account model with foreign key constraint to Employee
var Account = database.define('Account', {
name: Sequelize.STRING,
managerId: {
type: Sequelize.INTEGER,
references: {
// This is a reference to model Employee
model: Employee,
// This is the column name of the referenced model
key: 'id',
}
}
});
// 2. ROOM FOR MIDDLEWARE to use for all requests
router.use(function(req, res, next) {
// do logging
console.log('In server.js');
// make sure we go to the next routes and don't stop here
next();
});
// Initialize epilogue
epilogue.initialize({
app: app,
sequelize: database
});
app.use(express.static(__dirname + "/public"));
app.get('/', function(req, res) {
res.redirect('/public/index.html');
});
// 3. Create REST resource
var employeeResource = epilogue.resource({
model: Employee,
endpoints: ['/api/employees', '/api/employees/:id']
});
var acctResource = epilogue.resource({
model: Account,
endpoints: ['/api/accounts', '/api/accounts/:id']
});
// Create database and listen
database
.sync({
force: false
})
.then(function() {
app.listen(port, function() {
console.log('listening at %s', port);
});
});
I am using the nodemailer module here: https://github.com/andris9/Nodemailer in order to send an email automatically from a webapp. Having tested it with a PC browser using firefox, everything seems to work fine. However, when I am using an iphone safari to use the app it does not seem to send the email. Ive been scratching my head forever on this and I would be very grateful if anyone knew what was the reason for this!! Note I am using the gmail service, but I have set my gmail so that it sends the message as another address (in this case xyz#abc.com). My code is as follows below:
emailer module:
var nodemailer = require("nodemailer");
function sendEmail(firstname, email){
var smtpTransport = nodemailer.createTransport("SMTP",{
service: "Gmail",
auth: {
user: "user#gmail.com",
pass: "mypassword"
}
});
smtpTransport.sendMail({
from: "Sender <xyz#abc.com>",
to: email,
subject: "blahblah",
text: "blah blah blah",
}, function(error, response){
if(error){
console.log(error);
} else{
console.log("Success!");
}
});
}
exports.sendEmail = sendEmail;
app module:
var express = require("express");
var fs = require("fs");
var clientEmail = require("./clientEmail.js");
var profileEmail = require("./profileEmail.js");
var app = express();
app.use('/css', express.static(__dirname + '/css'));
app.use('/img', express.static(__dirname + '/img'));
app.use('/javascript', express.static(__dirname + '/javascript'));
app.use(express.bodyParser());
var buf = fs.readFileSync("html/index.html");
var index = buf.toString();
app.get('/', function(request, response) {
response.send(index);
});
app.post('/', function(request, response){
var email = request.body.email;
var name = request.body.name;
var firstname = request.body.firstname;
clientEmail.sendEmail(firstname,email);
response.redirect('/');
});
var port = process.env.PORT || 5000;
app.listen(port, function() {
console.log("Listening on " + port);
});
I have solved the issue. It was unrelated to nodemailer, I was actually using the toSource() function in my javascript which is not safari compatible. thanks all for your help