rethinkdb changesfeed in express with socket.io displaying [object object] - javascript

I'm using express.js, rethinkdb, thinky, socket.io. Trying to notify the index page of any changes that happens in the db. So I use rethinkdb changesfeed (and I can see the updates in console.log) but the cursor/feed is showing object object instead of the data.
When I pass the feed results to the socket.emit, it displays [object object]?
I read and implemented the code that comes from the rethinkdb blog (https://www.rethinkdb.com/blog/cats-of-instagram/) but it is not working.
Please scroll down to the bottom with socket.io header
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 r = require('rethinkdb');
// *********** Thinky code*********************//
var changeStream = require("rethinkdb-change-stream");
var thinky = require('thinky')()
var type = thinky.type;
var r = thinky.r;
//thinky model
var User = thinky.createModel('User', {
author: type.string()
});
/*
User.changes().then(function (feed) {
feed.each(function (error, doc) {
if (error) {
console.log(error);
process.exit(1);
}
if (doc.isSaved() === false) {
console.log("The following document was deleted:");
console.log(JSON.stringify(doc));
}
else if (doc.getOldValue() == null) {
console.log("A new document was inserted:");
console.log(JSON.stringify(doc));
}
else {
console.log("A document was updated.");
console.log("Old value:");
console.log(JSON.stringify(doc.getOldValue()));
console.log("New value:");
console.log(JSON.stringify(doc));
}
});
}).error(function (error) {
console.log(error);
process.exit(1);
});
*/
//*********End Thinky Code ******************//
// Mongodb Example http://www.guru99.com/node-js-mongodb.html
var MongoClient = require('mongodb').MongoClient
var url = 'mongodb://localhost/EmployeeDB';
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
//attach socket server to express server so it interacts with clients requests and responses
app.io = require('socket.io')();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(require('stylus').middleware(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'public')));
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: {}
});
});
/* )))))))))))))))) socket.io Header ((((((((((((((((((( */
app.io.on('connection', function (socket) {
r.connect(host = 'localhost', port = 28015, db = 'test').then(function (conn) {
this.conn = conn;
return r.table("User").changes().run(this.conn).then(function (cursor) {
cursor.each(function (err, item) {
console.log(item);
//if (item && item.new_val)
socket.emit("message-from-server", { greeting: item });
});
})
});
// socket.emit("message-from-server", { greeting: "Say whatever here- it will show on the index page"});
});
module.exports = app;

From your code:
console.log(item);
//if (item && item.new_val)
socket.emit("message-from-server", { greeting: item });
This tells me that item is probably an object so when you pass it to the web api to add to the DOM it renders the object reference [object Object] because its expecting a string (not an object). So you can pull out the info you want from item using . syntax for objects or [<index>] syntax for arrays, or you could do something like item.toString() to attempt to turn the whole thing into a string. It really depends on the structure of item and how you are adding it to the DOM. You could do it on the client side or do it before it's emitted from your server.

Related

Passing Mongo DB Object DB to Express Middleware

I am having problems trying to access the "DB" database object that is created when the MongoDB client module connects to my MongoDB database.
At the moment I am getting an error stating that, within data.js, 'db' is not defined. I understand why this is - the db object is not being "passed" through to the router and then subsequently through to the controller.
What is the best way to do this?
I have tried to pass the "db" object through to the router (dataRoutes.js) but I cannot figure how to make this accessible to the controller (data.js). Could someone please help?
Please note I have not included the other routes and controllers but they simply submit a Form via the POST method to /data/submit . The controller below is meant to write this form data to the MongoDB database.
Here is the relevant code:
app.js
var express = require('express');
var path = require('path')
var MongoClient = require('mongodb').MongoClient;
var bodyParser = require('body-parser');
var app = express();
var routes = require('./routes/index');
var dataRoutes = require('./routes/dataRoutes');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public')));
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
MongoClient.connect("mongodb://localhost:27017/m101", function(err, db) {
if(err) throw err;
console.log("Successfully connected to MongoDB.");
app.use('/', routes); // Use normal routes for wesbite
app.use('/data', dataRoutes);
app.get('/favicon.ico', function(req, res) {
res.send(204);
});
app.use(function(req, res, next) {
var err = new Error('Oops Page/Resource Not Found!');
err.status = 404;
next(err); //Proceed to next middleware
});
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
// update the error responce, either with the error status
// or if that is falsey use error code 500
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
app.use(function(err, req, res, next) {
console.log('Error');
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
var server = app.listen(3000, function() {
var port = server.address().port;
console.log("Express server listening on port %s.", port);
});
});
dataRoutes.js
// router
var express = require('express');
var router = express.Router();
// controller references
var ctrlsData = require('../controllers/data');
router.post('/submit', ctrlsData.submit);
module.exports = router;
data.js
var MongoClient = require('mongodb').MongoClient;
var sendJsonResponse = function(res, status, content) {
res.status(status);
res.json(content);
};
module.exports.submit = function(req, res) {
var title = req.body.title;
var year = req.body.year;
var imdb = req.body.imdb;
/*
console.log('submitted');
console.log(req.body);
sendJsonResponse(res, 201, {title,year,imdb});
*/
var title = req.body.title;
var year = req.body.year;
var imdb = req.body.imdb;
if ((title == '') || (year == '') || (imdb == '')) {
sendJsonResponse(res, 404, {
"message": "Title, Year and IMDB Reference are all required."
});
} else {
db.collection('movies').insertOne(
{ 'title': title, 'year': year, 'imdb': imdb },
function (err, r) {
if (err) {
sendJsonResponse(res, 400, err);
} else {
sendJsonResponse(res, 201, "Document inserted with _id: " + r.insertedId + {title,year,imdb});
}
}
);
}
};
Create a db variable that reference mongodb in app.js :
MongoClient.connect("mongodb://localhost:27017/m101", function(err, db) {
app.db = db;
//.....
});
In data.js, access db from req.app :
module.exports.submit = function(req, res) {
req.app.db.collection('movies').insertOne({ 'title': title, 'year': year, 'imdb': imdb },
function(err, r) {}
)
};
The accepted answer isn't quite correct. You shouldn't attach custom objects to the app object. That's what app.locals is for. Plus, the accepted answer will fail when using Typescript.
app.locals.db = db;
router.get('/foo', (req) => {
req.app.locals.db.insert('bar');
});
Sure, it's longer. But you get the assurance that future updates to ExpressJS will not interfere with your object.
I understand that the answer of #Bertrand is functional, but it is not usually recommended. The reason being that, from a software point of view, you should have a better separation in your software.
app.js
var express = require('express');
var path = require('path')
var MongoClient = require('mongodb').MongoClient;
var bodyParser = require('body-parser');
var app = express();
var routes = require('./routes/index');
var dataRoutes = require('./routes/dataRoutes');
var DB = require('./db.js');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public')));
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
DB.Init("mongodb://localhost:27017/m101")
.then(() => {
console.log("Successfully connected to MongoDB.");
app.use('/', routes); // Use normal routes for wesbite
app.use('/data', dataRoutes);
app.get('/favicon.ico', function(req, res) {
res.send(204);
});
var server = app.listen(3000, function() {
var port = server.address().port;
console.log("Express server listening on port %s.", port);
});
})
.catch((e) => {
console.log("Error initializing db");
});
db.js
var _db = null;
module.exports = {
Init: (url) => {
return new Promise((resolve, reject) => {
if (!url)
reject("You should provide a URL");
MongoClient.connect("mongodb://localhost:27017/m101", function(err, db) {
if(err) reject(err);
_db = db;
resolve(); // Or resolve(db) if you wanna return the db object
});
});
},
Submit: (req, res, next) => {
// Whatever goes. You have access to _db here, too!
}
};
in data.js
var DB = require('../db.js');
router.post('/submit', DB.submit);
Finally, even this answer can be improved as you are not usually advised to wait for the DB to connect, otherwise, you are losing the advantage of using ASync procs.
Consider something similar to here in app.js:
Promise.resolve()
.then(() => {
// Whatever DB stuff are
// DB.Init ?
})
.then(() => {
// Someone needs routing?
})
...
.catch((e) => {
console.error("Ther app failed to start");
console.error(e);
});
I understand that in the last sample, you can not instantly query DB as it may not have connected yet, but this is a server, and users are usually expected to wait for your DB to init. However, if you wanna more proof solution, consider implementing something yourself in DB.submit to wait for the connect. Or, you can also use something like mongoose.

NodeJS server crash after save data to mongoDB

I wrote a script which save an object to a MongoDB database using mongoose. The object is correctly save to the database, but the server crashes right after, throwing me the following error message: catch(err) { process.nextTick(function() { throw err}); }
Here's a part of my code:
users.js
var User = require('../models/user');
router.post('/register', function(req, res, next) {
[...]
// checks for errors
var errors = req.validationErrors();
if (errors) {
res.render('register', {
errors: errors,
[...]
})
} else {
var newUser = new User({
[...]
});
// Create user
User.createUser(newUser, function(err, user) {
if (error) {
throw err;
};
console.log(user);
});
[...]
}
});
module.exports = router;
user.js
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/nodeauth');
// User Schema
var UserSchema = mongoose.Schema({
[...]
});
var User = module.exports = mongoose.model('User', UserSchema);
module.exports.createUser = function(newUser, callback) {
newUser.save(callback);
}
apps.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
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 expressValidator = require('express-validator');
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
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 }));
// handle express session
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')));
// connect flash
app.use(flash());
app.use(function (req, res, next) {
res.locals.messages = require('express-messages')(req, res);
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;
You shouldn't throw error you should return it in handler to let clients know if there is a database error creating the user. Only throw when caller can catch error, async code cannot be caught easily. Promises enable throwing errors but not callbacks.

Using MongoDB, Express, Node.Js and GridFS-stream for storing video and picture files

I am creating a single page application using JavaScript(JQuery) and need to store large video files which size exceed 16Mb. I found that need to use GridFS supporting large files. As I am the new one to MongoDB I am not sure how to use GridFS. There are some good tutorials on creating applications using Node.js, MongoDB and Express but cant find any describing how to use GridFS with MongoDB (not mongoose), Express and Node.js. I managed to put up stuff for uploading files in the BSON-document size limit of 16MB. This is what I have:
var express = require('express');
var path = require('path');
var bodyParser = require('body-parser');
var mongo = require('mongodb');
var monk = require('monk');
var Grid = require('gridfs-stream');
var db = monk('localhost:27017/elearning');
var gfs = Grid(db, mongo);
var routes = require('./routes/index');
var users = require('./routes/users');
var courses = require('./routes/courses');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
// Make our db accessible to our router
app.use(function(req,res,next){
req.db = db;
next();
});
app.use('/', routes);
app.use('/users', users);
app.use('/courses', courses);
// 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;
And, for example, the courses file is as the following:
var express = require('express');
var router = express.Router();
/* GET courses listing */
router.get('/courselist', function(req, res) {
var db = req.db;
var collection = db.get('courselist');
collection.find({},{},function(e,docs){
res.json(docs);
})
});
/* POST courses data */
router.post('/courselist', function(req, res) {
var db = req.db;
var collection = db.get('courselist');
collection.insert(req.body, function(err, result){
res.send(
(err === null) ? { msg: '' } : { msg: err }
);
});
});
/* Delete courses data */
router.delete('/courselist/:id', function(req, res) {
var db = req.db;
var collection = db.get('courselist');
var userToDelete = req.params.id;
collection.remove({ '_id' : userToDelete }, function(err) {
res.send((err === null) ? { msg: '' } : { msg:'error: ' + err });
});
});
module.exports = router;
I would be extremely grateful for your help, if you could tell how should I edit above files in order to utilize GridFS and be able to get, upload and delete video and picture files from my elearning database.
You can do direct uploading without using mongoose using gridfs-stream as simple as:
var express = require('express'),
mongo = require('mongodb'),
Grid = require('gridfs-stream'),
db = new mongo.Db('node-cheat-db', new mongo.Server("localhost", 27017)),
gfs = Grid(db, mongo),
app = express();
db.open(function (err) {
if (err) return handleError(err);
var gfs = Grid(db, mongo);
console.log('All set! Start uploading :)');
});
//POST http://localhost:3000/file
app.post('/file', function (req, res) {
var writeStream = gfs.createWriteStream({
filename: 'file_name_here'
});
writeStream.on('close', function (file) {
res.send(`File has been uploaded ${file._id}`);
});
req.pipe(writeStream);
});
//GET http://localhost:3000/file/[mongo_id_of_file_here]
app.get('/file/:fileId', function (req, res) {
gfs.createReadStream({
_id: req.params.fileId // or provide filename: 'file_name_here'
}).pipe(res);
});
app.listen(process.env.PORT || 3000);
for complete files and running project:
Clone node-cheat direct_upload_gridfs, run node app followed by npm install express mongodb gridfs-stream.
OR
Follow baby steps at Node-Cheat Direct Upload via GridFS README.md
Very late but I found previous answer outdated. I'm posting this because this might help newbies like me. To run it, please follow previous answers guide. All credit goes to #ZeeshanHassanMemon.
var express = require('express'),
mongoose = require('mongoose'),
Grid = require('gridfs-stream'),
app = express();
Grid.mongo = mongoose.mongo;
conn = mongoose.createConnection('mongodb://localhost/node-cheat-db');
conn.once('open', function () {
var gfs = Grid(conn.db);
app.set('gridfs', gfs);
console.log('all set');
});
//POST http://localhost:3000/file
app.post('/file', function (req, res) {
var gridfs = app.get('gridfs');
var writeStream = gridfs.createWriteStream({
filename: 'file_name_here'
});
writeStream.on('close', function (file) {
res.send(`File has been uploaded ${file._id}`);
});
req.pipe(writeStream);
});
//GET http://localhost:3000/file/[mongo_id_of_file_here]
app.get('/file/:fileId', function (req, res) {
var gridfs = app.get('gridfs');
gridfs.createReadStream({
_id: req.params.fileId // or provide filename: 'file_name_here'
}).pipe(res);
});
app.listen(process.env.PORT || 3000);

Querying MongDB database using NodeJS and jQuery

I am stuck trying to query my database built using MongoDB (with Mongoose as the ODM) and displaying the results on the page. The database stores the data (comprising of date: 'date', and link: 'wwww.example.com') in a collection I named 'entries'. I have two views that I want to use to access the database: a view which will utilize the date key to display the right link on a particular day; and a view of the database where I can view, add and delete entries. I was somehow able to loop through the entries for the database view and add them to the DOM but when I try the same for the widget view I can't seem to access the JSON object from the entries collection. I'm using Jade as a preprocessor for my HTML
My app.js file is like so:
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 router = express.Router();
//database stuff
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
//connect to the data store and the set up the database
var db = mongoose.connection;
//connect to the database
var conn = mongoose.connect('mongodb://localhost/Mandela_Diaries/data');
//Create a model which connects to the schema and entries collection in the Mandela_Diaries database
var Entry = mongoose.model("Entry", new Schema({date: 'date', link: 'string'}), "entries");
mongoose.connection.on("open", function() {
console.log("mongodb is connected!");
});
var routes = require('./models/index');
var users = require('./routes/users');
var database = require('./routes/database');
var methodOverride = require('method-override');
var templatemain = require('./routes/template-main');
var app = express();
// Methodoverride at the top
app.use(methodOverride('_method'));
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
//serving static files
app.use('/public', express.static(__dirname + '/public'));
app.use('/public', express.static(__dirname + '/css'));
app.use('/public', express.static(__dirname + '/js'));
app.use('/public', express.static(__dirname + '/images'));
app.use('/public', express.static(__dirname + '/node_modules'));
app.use('/', routes);
app.use('/', routes);
app.use('/', routes);
app.use('/database', database);
app.use('/create', database);
app.use('/delete', database);
app.use('/:id', database);
// app.use('/database/#{entry._id}?/delete', database);
// 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;
module.exports.Entry = Entry;
app.listen(8080);
console.log("The server has started");
My database.js router code is like so:
var express = require('express');
var router = express.Router();
var mongoose = require('mongoose');
var Entry = mongoose.model('Entry');
//The route for getting data for the database - GET form
router.get("/", function(req, res) {
//Send the current entries to the page
Entry.find({}, function(err, entries) {
console.log(entries);
if(err) {
res.status(404).json({"error": "not found", "err":err});
return;
} else {
res.render('database', {title: 'database', entries: entries});
//console.log(entries);
//entries.forEach(printjson);
}
});
});
//The route for posting data to the database - POST
router.post('/', function(req, res) {
var newEntry = new Entry(req.body);
newEntry.save(function(err, entries){
if (err !== null) {
res.status(500).json(err);
} else {
res.redirect('database');
};
});
});
//The route for deleting data to the database - Delete/remove todo item by its id
// Changed path from `/` to `/:id`
router.delete('/:id', function (req, res) {
Entry.findById(req.params.id)
.exec(function(err, entries) {
// changed `if (err || !doc)` to `if (err || !entries)`
if (err || !entries) {
res.statusCode = 404;
res.send({});
} else {
entries.remove(function(err) {
if (err) {
res.statusCode = 403;
res.send(err);
} else {
res.send('Deleted entry with link: ', entries.link);
}
});
}
});
});
module.exports = router;
My index.js router code is like so:
var express = require('express');
var router = express.Router();
var mongoose = require('mongoose');
var Entry = mongoose.model('Entry');
var moment = require('moment');
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('/', { title: 'Express' });
Entry.find({}, function(err, entries) {
if(err) {
res.status(404).json({"error": "not found", "err":err});
return;
} else {
res.render('/', {title: 'database', entries: entries});
}
});
});
console.log("new code works");
module.exports = router;
My script.js code running the jQuery to append the correct video links according to the date is like so:
$(document).ready(function() {
//Date picker jQuery
$(function() {
$( ".datepicker" ).datepicker();
$( "#format" ).change(function() {
$( ".datepicker" ).datepicker( "option", "dateFormat", $( this ).val() );
});
});
var browserDate = new Date();
var videoDate = new Date(1962);
//var month = browserDate.getMonth() + 1;
//var day = browserDate.getDate();
//var year = browserDate.getFullYear();
var context = browserDate - videoDate;
$('#context').innerHTML = "ON THIS DAY " + context + " YEARS AGO:";
console.log("ON THIS DAY " + context + " YEARS AGO:");
console.log("This worked!!");
console.log(browserDate);
});
And my Jade code for index.jade is like this:
extends layout
block content
#widget.container
.row
#header.col-xs-12.header
img#Mandela_Logo(src='/public/images/Logo_MandelaDiaries.png')
.row
#context.col-xs-12
.row
#videos.col-xs-12
.embed-responsive.embed-responsive-4by3
iframe(width='300', height='169', src='https://www.youtube.com/embed/4HqtAMHrJ8s', frameborder='0', allowfullscreen='')
.row
#footer.col-xs-12
img#NMF_logo(src='/public/images/Logo_NMF.png')
img#SABC_logo(src='/public/images/Logo_SABCNews.png')
I can't seem to be able to get my jQuery to work here. I just want to get the JSON object and loop through it and find the relevant day, based on the browser date, and attach the corresponding link to the iframe in my widget.
To simplify things, you could use the momentjs library which is great at dealing with dates. In your use case, you want to use the fromNow() method which displays the relative time from now, say for example
moment([2011, 0, 29]).fromNow(); // 4 years ago
moment("1962-04-08T09:48:16.189Z").fromNow() // 53 years ago
To use the momentjs library in your views, you need to add it to your express application locals as follows:
express = require('express');
...
var app = express();
app.locals.moment = require('moment');
Since you can use plain JavaScript code in in your Jade views, you can easily do:
extends layout
block content
#widget.container
.row
#header.col-xs-12.header
img#Mandela_Logo(src='/public/images/Logo_MandelaDiaries.png')
.row
#context.col-xs-12
each entry in entries
p= 'ON THIS DAY ' + moment(entry.date).fromNow() + ' - Link: ' + entry.link + ' '
.row
#videos.col-xs-12
.embed-responsive.embed-responsive-4by3
iframe(width='300', height='169', src='https://www.youtube.com/embed/4HqtAMHrJ8s', frameborder='0', allowfullscreen='')
.row
#footer.col-xs-12
img#NMF_logo(src='/public/images/Logo_NMF.png')
img#SABC_logo(src='/public/images/Logo_SABCNews.png')
Demo
Source: Making use of utility libraries in server-side Jade templates

Routes issue in Express 4

Noob - trying to set up CRUD using routes on Express4 and Node. I've got the following GET and POST routes working ok, but DELETE and PUT are giving 404, Not Found errors, which is strange.
I'm using Postman for Chrome and have set the Content Type to application/json, and this is working ok - i do notice that on the DELETE and PUT queries the header still notes that it's sending as text/html, rather than JSON, although I've set both the RAW settings to JSON, and the Headers content type manually to application/json.
var express = require('express');
var router = express.Router();
var mongoose = require('mongoose');
var Todo = require('../models/Todo.js');
/* GET /todos listing. THIS IS WORKING*/
router.get('/', function(req, res, next) {
Todo.find(function (err, todos) {
if (err) return next(err);
res.json(todos);
});
});
/* POST /todos listings THIS IS WORKING*/
router.post('/', function(req, res, next){
Todo.create(req.body, function(err, post){
if (err) return next(err);
res.json(post);
});
});
/* GET /todos/id THIS IS WORKING*/
router.get('/:id', function(req, res, next) {
Todo.findById(req.params.id, function (err, post) {
if (err) return next(err);
res.json(post);
});
});
/* DELETE /todos/:id NOT WORKING*/
router.delete('/:id', function(req, res, next) {
console.log(req);
Todo.findByIdAndRemove(req.params.id, req.body, function (err, post) {
if (err) return next(err);
res.json(post);
});
});
module.exports = router;
Also this is a routes.js script that is being imported into app.js (see below):
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 routes = require('./routes/index');
var todos = require('./routes/todos');
// set our port
var port = process.env.PORT || 3000;
//Requires the mongoose connection
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/todoApp', function(err) {
if(err) {
console.log('connection error', err);
} else {
console.log('connection successful');
}
});
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/todos', todos);
// 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: {}
});
});
// start app ===============================================
// startup our app at http://localhost:3080
app.listen(port);
// shoutout to the user
console.log('Magic happens on port ' + port);
module.exports = app;
I looked into your implementation, it looks fine. Just one chance where i feel it can go wrong is, if we look into the documentation of Model.findOneAndRemove(conditions, [options], [callback]), you are going wrong in [options].
In [options] we can do :
sort: if multiple docs are found by the conditions, sets the sort
order to choose which doc to update
select: sets the document fields to return
Try this, i hope it will solve your problem.
You mentioned that, PUT is also having same 404 issue, could you please update your post by including same. Let's understand where it is going wrong.
There's a couple of things you might want to check.
Your POST is working as intended, but your DELETEs and your PUTs aren't. You've set the content type to application/json.
Given that you are using Express 4, and had to include a body parser yourself, do you happen to include the following lines?
var app = express();
// you probably have this, for application/x-www-form-urlencoded
app.use(bodyParser.urlencoded());
// extrapolating here, you only mentioned you were receiving 404s.
// you might be missing the following line?
app.use(bodyParser.json());
In your delete route, you log the response object, is this a typo? A more useful log would be of the request object - so you can determine what exactly the route thinks you sent.
Shot in the dark, but in the absence of additional information, I hope at least one of the answers are correct.

Categories