I am using NodeJS and ExpressJS to implement a RESTful API server for a simple backend. I am also using BackboneJS to render views in the front. Therefore, right now I have a single index.html file that I want to render when the client sends a /GET to the '/' route. This is what I have so far:
var express = require('express');
var app = express();
app.use(express.bodyParser());
var mongo = require('mongodb');
var mongoose = require('mongoose');
var Server = mongo.Server,
DB = mongo.Db,
BSON = mongo.BSONPure;
var server = new Server('localhost', 27017, {auto_reconnect: true});
db = new DB('mydb', server, {safe: true});
db.open(function(err, db) {
if(!err) {
console.log("Connected to 'mydb' database");
db.collection('items', {safe:true}, function(err, collection) {
if (err) {
console.log("Creating collection 'items'");
}
});
}
});
var port = process.env.PORT || 3000;
app.engine('.html');
var listItems = function(req, res){
db.collection('items', function(err, collection){
var items = collection.find();
console.log(items);
res.send(items);
});
}
var itemDetails = function(req, res){
}
var deleteItem = function(req, res){
}
var createItem = function(req, res){
}
var updateItem = function(req, res){
}
var routeHome = function(req, res){
// What can I do here to render a plain .html file?
}
app.all('*', function(req, res, next){
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header("Content-Type", "application/json");
next();
});
app.get('/', routeHome);
app.get('/items', listItems);
app.get('/items/:id', itemDetails);
app.del('/users/:id', deleteItem);
app.post('/users', createItem);
app.put('/users/:id', updateItem);
app.listen(port);
console.log("Server started up on port " + port);
As you can see I have everything set up except I cannot figure out how to send a regular .html file to the client. I do not need a rendering engine because Backbone is doing all that for me. I just want to get index.html to go to the client.
How about just using the express.static middleware? Since you're using Backbone, you might have the need for sending static JS files as well:
app.use(express.static(__dirname));
Place that somewhere before your other routes. It will try and find files requested in __dirname (the directory where your app.js file resides, but you can of course change the location where the middleware will try and find files), including index.html.
Step One, Remove app.engine(".html"),
Step Two:
var routeHome = function(req, res){
// Do What Ever
res.sendFile("index.html",function(err){ // Transfer The File With COntent Type Text/HTML
if(err){
res.end("Sorry, Error.");
}else{
res.end(); // Send The Response
}
})
}
Related
I am working on to do list app using mongoDB and node.js. Basically you type what you want to do then click add. I successfully connected the database but it doesn't show the text that's in the database. It shows only the bullets in the localhost.
Here's the code:
app.get('/', function(req, res) {
db.collection('list').find().toArray(function (err, result) {
console.log(result);
if (err) {return};
console.log(err);
res.render('index.ejs', {list: result})
});
});
app.post('/', function(req, res){
console.log(req.body);
db.collection('list').save(req.body, function(err, result) {
if (err) {return};
console.log(err);
console.log('saved')
res.redirect('/');
})
})
I have validated the code you posted and have revised it slightly with comments.
I hope this helps but it seems that the fault might be in the res.render method that is being used. Please refer to the following code:
// Requires
var express = require('express');
var bodyParser = require('body-parser');
var MongoClient = require('mongodb').MongoClient;
// Instantiation
var app = express();
var mongopath = "mongodb://localhost:27017/BitX";
// Port number the REST api works on
var portnum = 7500;
// MongoDB object
var db = null;
MongoClient.connect(mongopath, function(err,ldb){
db = ldb;
});
// Implement Body Parser
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(bodyParser.json());
// Start the REST service
var server = app.listen(portnum, function() {
var host = server.address().address;
var port = server.address().port;
console.log("Content Provider Service listening at http://%s:%s", host, port);
});
// Default route
app.get('/', function(req, res) {
// Find all items in orders and send back results to a front end
db.collection('orders').find().toArray(function (err, result) {
res.send(result);
// Consider that the rendering engine may not be functioning correctly
// SEE MORE: https://stackoverflow.com/questions/21843840/what-does-res-render-do-and-what-does-the-html-file-look-like
//res.render('index.ejs', {list: result})
});
});
// Accept a post on the root
app.post('/', function(req, res){
//Save into orders
db.collection('orders').save(req.body, function(err, result) {
res.send(true);
//res.redirect('/');
});
});
For additional information on the res.render method please have a look at:
What does "res.render" do, and what does the html file look like?
- if you have not already.
Hope it helps!
I'm learning Node, Express, Jade & Mongodb. I'm unable to display my mongodb documents in jade. I'm unable to figure it out on my own. I'm successfully logging all documents using console.log and it display all the documents correctly. Please no mongoose or other solutions. Just how to build on this code. I already connected to the db, displayed all documents in terminal. How to be able to pass it to Jade and display it in view.jade?
Thanks.
Here is my app.js code
var express = require('express');
var app = express();
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
// Mongodb Example http://www.guru99.com/node-js-mongodb.html
var MongoClient = require('mongodb').MongoClient
var url = 'mongodb://localhost/EmployeeDB';
MongoClient.connect(url, function(err, db) {
//Insert data into mongodb db. If the collection doesn't exist, it will be created with the first inserted document
db.collection('employee').insertOne({
number : 17,
name: "aaa"
});
//Updating Documents in a collection
db.collection('employee').updateOne(
{"name": "New Employee"}, {$set: {"name": "AA"}}
);
//Deleting Documents in a collection
db.collection('employee').deleteOne(
{ "name": "name" }
);
// no need to pass a second parameter. Just the name of the field to be deleted.
//Querying for data in mongodb db .
var cursor = db.collection('employee').find();
cursor.each(function (err, doc) {
//console.log(doc)
});
console.log("connected");
db.close();
});
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');
// 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: {}
});
});
module.exports = app;
Here is my index.js
var express = require('express');
var router = express.Router()
//the global str variable is accessable from anywhere and logging the db.collection but how I pass it to jade?
var str = "";
/* GET home page. and iterate, display the collection to console log. */
router.get('/', function (req, res) {
var MongoClient = require('mongodb').MongoClient
var url = 'mongodb://localhost/EmployeeDB';
MongoClient.connect(url, function (err, db) {
var str = db.collection('employee').find();
str.each(function (err, doc) {
console.log(doc);
});
//How to pass the .db.collection documents to Jade?
res.render('index');
});
});
Here is my index.jade file
extends layout
block content
h1= title
https://naltatis.github.io/jade-syntax-docs/ Has useful information for view.jade files
index.js needs an array to hold the mongo results:
var results_from_mongo = [];
and everytime we get a result from the query, let's push it onto the array (array language for "insert an element into the array")
results_from_mongo.push(doc); //Push result onto results_array
then we must simply send it along to res.render:
res.render('index', {"results": results_from_mongo });
So in your index.js file
/* GET home page. and iterate, display the collection to console log. */
router.get('/', function (req, res) {
var MongoClient = require('mongodb').MongoClient
var url = 'mongodb://localhost/EmployeeDB';
var results_from_mongo = [];
MongoClient.connect(url, function (err, db) {
var str = db.collection('employee').find();
str.each(function (err, doc) {
console.log(doc);
results_from_mongo.push(doc); //Push result onto results_array
});
//now we have a results array filled like this:
// results_from_mongo = ["some string", "some string", "some string"]
//so let's pass them to the jade file to render them.
res.render('index', {"results": results_from_mongo });
//this will pass the data in JSON format to the JADE file called 'index' (index.jade)
The data at this point looks like
{ "results" : ["some string", "some string", "some string"] }
and in index.jade we can do something like
extends layout
block content
h1= title
h2= "results from mongo:"
select
each mongo_result, i in results
div Result #{i} #{mongo_result}
The jade (now pug) file needs to be set up to show a table, if you want to send an array from the database to be displayed as html. Here is the relevent code that I use for my table layout in a sample index.pug file.
table
thead
tr
th Flight Date
th Tail Number
th Origin
th Destination
th Dep
th Arr
tbody
each mongo_result, i in results
tr
td= mongo_result.flight_date
td= mongo_result.tail_num
td= mongo_result.origin_airport_code
td= mongo_result.dest_airport_code
td= mongo_result.dep_time
td= mongo_result.arr_time
In this example, under the table header thead, I am setting up the captions for the header row of the table. Then under tbody, I am specifying the actual data I want pug to pull from each row of the array that is pushed to it. Pug is very sensitive to indentation with white space characters: it requires it. So you need to pay close attention to indentation or the results won't work as expected.
You can use the db() method to handle the collection:
var data = [];
router.get('/', function (req, res) {
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost:27017/'; // do not put db in url, EmployeeDB
MongoClient.connect(url, function (err, db) {
if (err) throw err;
var dbo = db.db("EmployeeDB");
dbo.collection("employee").find({}).toArray(function(err, result) {
if (err) throw err;
data = result;
db.close();
});
});
res.render('index',{ data_employee : data });
});
});
And you must update your index.jade (or index.pug) file:
extends layout
block content
div.main
table
thead
tr
th name
th surname
tbody
each data in data_employee
tr
td= data.name
td= data.surname
Im trying to use a param in a route... tried the 4.x docs on express website but no use.. im still getting 404... seems like its not hitting my function..
The other routes to create and list all itens are fine..
var db = require('../db');
var express = require('express');
var mongoose = require( 'mongoose' );
var Users = mongoose.model( 'Users' );
var app = express.Router();
//PARAM
app.param('name', function(req, res, next, name) {
Users.find({name:name}, function(err, docs) {
if (err) {
return next(err);
}
else if (!name) {
return next(new Error('failed to load user'));
}
req.user = docs[0];
next();
});
});
//SHOW
app.get('/users/:name', function(req,res){
res.render('users/profile', {user: req.user});
});
tried a simple version... same 404... (btw the name exist.. it shows on the list item)
//SHOW
app.get('/users/:name', function(req, res, name){
var name = req.param('name');
Users.find({name: name}, function(err, docs) {
req.user = docs[0];
next();
});
res.render('users/profile', {user: req.user});
});
It's because you're using an Express 4 Router like it's an Express 3 app. A Router lets you set up a collection of related routes, like you have done. However, you then must attach the Router to your larger Express server.
var express = require('express');
var app = express();
var router = express.Router();
// attach some things to router
// router.get('/users/:name', ...)
app.use('/foo', router);
Would mount all the paths that router handles under the /foo path, like /foo/users/:name.
My project goal is to make a checklist-like web app where the user can see what's in the database and also update what's inside it.
Database is simple. Just listing favorite things. Eg {"favorite":"Pie"},{"favorite":"Kitty"}
So far I've figured out how to connect to the database(MongoHQ) and show a single element of data. I've been trying for hours but I'm stumped on:
Getting the html file to write whatever data is in the database.
Writing the Post form to write to the database.
Please share some insights!
Here's my code.
.html
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div>
<h1>Notepad</h1>
<p>Favorite things: {{favorite}}</p>
<!-- {% for favorite in doc %} <-this doesn't work!
<p>Favorite things: {{favorite}}</p>
{% endfor %}
-->
</div>
</body>
</html>
web.js
var express = require('express');
var path = require('path');
var fs = require('fs');
var http = require('http');
var mongo = require('mongodb');
var MongoClient = mongo.MongoClient;
var Server = require('mongodb').Server;
var mongoUri = "mongodb://id:pass#ds------.mongolab.com:-----/heroku_app------";
var cons = require('consolidate');
var app = express(express.logger());
app.engine('html', cons.swig);
app.set('view engine', 'html');
app.set('views', __dirname + '/views');
app.set('port', process.env.Port || 8080);
app.use(express.bodyParser());
var mydatabase = null;
var myCollection = null;
MongoClient.connect(mongoUri, function(err, db){
if(!err){
console.log("We are connected to mongo_lab!");
}
mydatabase = db;
mydatabase.createCollection('test2', function(err, collection){});
myCollection = mydatabase.collection('favorites');
//myCollection.insert({'favorite':'Blueberries'}, {w:1}, function(err, result){});
});
var mongoclient_server = new MongoClient(new Server('localhost', 27017));
function errorHandler(err, req, res, next){
console.error(err.message);
console.error(err.stack);
res.status(500);
res.send("Fix the dam Error!");
}
app.use(errorHandler);
app.get('/notepad', function(req, res, next){
MongoClient.connect(mongoUri, function(err, db){
mydatabase.collection("favorites").find().toArray(function(err, doc){
if(err) throw err;
console.log(doc);
res.render('notepad', doc[0]);
});
});
});
var htmlfile = "index.html";
app.get('/', function(request, response) {
var html = fs.readFileSync(htmlfile).toString();
response.send(html);
});
var port = process.env.PORT || 8080;
app.listen(port, function() {
console.log("Listening on " + port);
});
//mongoclient_server.open(function(err, mongoclient_server){ <--if I use this, heroku crashes
// if(err) throw err;
// app.listen(port);
//});
You're passing data from doc[0] as locals to your notepad view, so basically notepad locals will be what is in doc[0].
In your call to res.render(), you should specify that your documents reside in the doc local, like this:
res.render('notepad', {
doc: doc
});
This way your {% for ... %} will work.
Docs for res.render
I am getting my hands on node.js and I am trying to understand the whole require/exports thing. I have the following main app.js file:
/app.js
var express = require('express'),
http = require('http'),
redis = require('redis'),
routes = require('./routes'),
var app = express(),
client = redis.createClient();
// some more stuff here...
// and my routes
app.get('/', routes.index);
then, I have the routes file:
exports.index = function(req, res){
res.render('index', { title: 'Express' });
};
I can of course use the client object on my app.js file, but how can I use the same object in my routes?
Since req and res are already being passed around by Express, you can attach client to one or both in a custom middleware:
app.use(function (req, res, next) {
req.client = res.client = client;
next();
});
Note that order does matter with middleware, so this will need to be before app.use(app.router);.
But, then you can access the client within any route handlers:
exports.index = function(req, res){
req.client.get(..., function (err, ...) {
res.render('index', { title: 'Express' });
});
};
The easiest way is to export a function from your routes file that takes a client, and returns an object with your routes:
exports = module.exports = function (client) {
return {
index: function (req, res) {
// use client here, as needed
res.render('index', { title: 'Express' });
}
};
};
Then from app.js:
var client = redis.createClient(),
routes = require('./routes')(client);