I'm creating my first sample code using NodeJS, Express, MongoDB and Swig. It's a small blog application and I'm trying to render the existing posts, however, the post body contains HTML tags and they are printed as text.
How can I render them as HTML?
Here is my view (main.html):
<p>
<h3>{{title}}</h3>
<h6><i>{{postedAt}}</i></h6>
</p>
<p>
{{content}}
</p>
And here is the app.js:
var express = require('express');
var cons = require('consolidate');
var app = express();
var MongoClient = require('mongodb').MongoClient;
var Server = require('mongodb').Server;
app.engine('html', cons.swig);
app.set('view engine', 'html');
app.set('views', __dirname + '/views');
var mongoClient = new MongoClient(new Server('localhost', 27017,
{ 'native_parser' : true }));
var db = mongoClient.db('blog');
// Base URL - Show posts
app.get('/', function (request, response) {
var cursor = db.collection('posts').find().sort({'postedAt': 1});
cursor.each(function (err, doc) {
if (err) throw err;
if (doc == null) {
return db.close();
}
response.render('main', doc);
});
});
app.get('*', function (request, response) {
response.send('Page not found', 404);
});
mongoClient.open(function (err, client) {
if (err) throw err;
app.listen(8080);
console.log('Express started listening on port 8080');
});
Swig HMTL-escapes all variables by default.
If you’re sure the content in question is safe (i.e. the HTML doesn’t include malicious JavaScript), then you can turn off HMTL-escaping using the safe filter:
<p>
<h3>{{title}}</h3>
<h6><i>{{postedAt}}</i></h6>
</p>
<p>
{{content|safe}}
</p>
Related
While in / view, I get documents from mongodb and create a list item for each document that only shows the date and the first few words. I want to be able to click on each list item to go to a new page, /view, to see the rest of that particular document.
To do this, I believe I need to pass item between / and /view, then access the properties of item there. How do I do this with the pagelist function (or without it)?
index.js:
var express = require('express');
var exphbs = require('express-handlebars');
var bodyParser = require('body-parser');
var app = express();
var hbs = exphbs.create({
helpers: {
message: function() {return 'Welcome!';},
doc: function() {return "Something went wrong.";}
}
});
app.engine('handlebars', hbs.engine);
app.set('view engine', 'handlebars');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
const MongoClient = require('mongodb').MongoClient;
var assert = require('assert');
var util=require('util');
const url = 'mongodb://localhost:27017/users';
const dbName = 'users';
var db;
MongoClient.connect(url, function(err, client) {
assert.equal(null, err);
console.log("Connected successfully to server");
db = client.db(dbName);
db.collection("reviewYelp2", { }, function(err, coll) {
if (err != null) {
console.log(err)
db.createCollection("reviewYelp2", function(err, result) {
assert.equal(null, err);
});
}
db.ensureIndex("reviewYelp2", { document: "text"}, function(err, indexname) {
assert.equal(null, err);
});
});
});
app.get("/", function(req, res) {
res.render('search');
});
app.get("/view", function(req, res) {
// NEED TO BE ABLE TO ACCESS CLICKED ITEM HERE
res.render('viewItem', {
// Change to access item.text when I have access to item
helpers: {
doc: function() {return "Viewing doc...";}
}
});
});
app.post("/", function(req, res) {
db.collection('reviewYelp2').find({
text: new RegExp(req.body.query)
}).sort({date: 1}).toArray(function(err, items) {
res.render('search', {
helpers: {
message: function() {return pagelist(items);}
}
});
})
});
function pagelist(items) {
result = "<ul>";
items.forEach(function(item) {
// Grab only first 10 words of text
textSlice = item.text.split(" ");
textSlice = textSlice.slice(0, 5);
text = textSlice.join(" ");
str = "<li class="+item._id+"><a href='/view'>" + item.date + " " + text + "...</a></li>";
result = result + str;
});
result = result + "</ul>";
return result;
}
app.listen(3000, function() {
console.log("App listening on localhost:3000");
});
search.handlebars:
<!DOCTYPE html>
<html>
<body>
<form method="post">
<input type="text" size="80" name="query" />
<input type="submit" value="Search" class="submitButton" />
{{{ message }}}
</form>
</body>
</html>
viewItem.handlebars:
<!DOCTYPE html>
<html>
<body>
<button onclick="window.history.back()">Go back to list</button>
{{{ doc }}}
</body>
</html>
This is problematic because http is fundamentally stateless — that is each request to the server is it's own thing. You can come up with schemes involving cookies or local storage, but I think a simpler approach is both better and more common.
A simpler idea is to have a route that takes some sort of id parameter:
app.get("/view_detail/:itemID", function(req, res) {
var item = req.params.itemID
// lookup detail about item based on itemID
res.render('viewItem', {
// send data
});
});
Now on index you can have a list of links that look like :
/view/878743 (or whatever scheme you have for db keys)
/view/36764e
I made a upload image to a document and saved the path to the MongoDB , While retrieving the Image, It is showing only the current image which is being uploaded. I want to show all the images which is uploaded to the database. Please help me to display all the images from the Data base.
Thank you in advance :)
var express = require('express'); //Express Web Server
var busboy = require('connect-busboy'); //middleware for form/file upload
var path = require('path'); //used for file path
var fs = require('fs-extra'); //File System - for file manipulation
var mongoose = require('mongoose');
var handlebars = require('handlebars');
var mongoClient = require('mongodb').mongoClient;
var objectId = require('mongodb').ObjectId;
var app = express();
app.use(busboy());
app.use(express.static(path.join(__dirname, 'public')));
mongoose.Promise = global.Promise;
mongoose.connect('mongodb://localhost:27017/postname');
/* ==========================================================
Create a Route (/upload) to handle the Form submission
(handle POST requests to /upload)
Express v4 Route definition
============================================================ */
app.set('view engine', 'hbs');
app.set('views', path.join(__dirname, 'views'));
app.use(express.static(__dirname + '/public'));
//You can import your schema like this
const Name = require('./name');
app.get('/', function(req, res, next) {
res.render('index',{'title': 'New post app'});
});
//I have changed your route since it seems to be clashing with the above
app.post('/save' ,function (req, res, next) {
var fstream;
req.pipe(req.busboy);
req.busboy.on('file', function(fieldname, file, filename, done){
console.log("Uploading" + filename);
//path where the file is being uploaded
fstream = fs.createWriteStream(__dirname + '/public/uploads/' + filename);
var dirname = path.join( 'uploads/' + filename);
file.pipe(fstream);
fstream.on('close', function(){
console.log("Upload Success" + filename);
let name = new Name({
path: dirname
});
name.save((err)=>{
if(err) throw err;
console.log(`saved : ${name}`);
res.redirect('/profile');
call(dirname);
});
});
});
});
function call(dirname){
Name.findOne({path: dirname}, (err, result) =>{
if(err) throw err;
var imgpath = result.path;
console.log("Saved check" + imgpath);
app.get('/profile', (req, res) =>{
res.render('profile',{
photo: req.result,
result : imgpath
});
});
});
}
var server = app.listen(3030, function() {
console.log('Listening on port %d', server.address().port);
});
My name.js file Mongoose Schema
let mongoose = require('mongoose');
let Schema = mongoose.Schema;
let compileSchema = new Schema({
path: String
});
let Compile = mongoose.model('Compiles', compileSchema);
module.exports = Compile;
Views File to display the image
<html>
<head>
<title>User Profile</title>
</head>
<body>
<h1>Welcome</h1>{{result}}<br><br>
<img src="{{result}}" height="180" width="250">
</body>
</html>
You are using findOne which only retrieves one object from the database. So if you want to retrieve all the images your code should be something like this :
var express = require('express') // Express Web Server
var busboy = require('connect-busboy') // middleware for form/file upload
var path = require('path') // used for file path
var fs = require('fs-extra'); // File System - for file manipulation
var mongoose = require('mongoose')
var handlebars = require('handlebars')
var mongoClient = require('mongodb').mongoClient
var objectId = require('mongodb').ObjectId
var app = express()
app.use(busboy())
app.use(express.static(path.join(__dirname, 'public')))
mongoose.Promise = global.Promise
mongoose.connect('mongodb://localhost:27017/postname')
/* ==========================================================
Create a Route (/upload) to handle the Form submission
(handle POST requests to /upload)
Express v4 Route definition
============================================================ */
app.set('view engine', 'hbs')
app.set('views', path.join(__dirname, 'views'))
app.use(express.static(__dirname + '/public'))
// You can import your schema like this
const Name = require('./name')
app.get('/', function (req, res, next) {
res.render('index', {'title': 'New post app'})
})
// I have changed your route since it seems to be clashing with the above
app.post('/save' , function (req, res, next) {
var fstream
req.pipe(req.busboy)
req.busboy.on('file', function (fieldname, file, filename, done) {
console.log('Uploading' + filename)
// path where the file is being uploaded
fstream = fs.createWriteStream(__dirname + '/public/uploads/' + filename)
var dirname = path.join( 'uploads/' + filename)
file.pipe(fstream)
fstream.on('close', function () {
console.log('Upload Success' + filename)
let name = new Name({
path: dirname
})
name.save((err) => {
if (err) throw err
console.log(`saved : ${name}`)
res.redirect('/profile')
// removed call(), no need for it
})
})
})
})
app.get('/profile', (req, res) => {
// get all documents in the db by using find with no conditions
Name.find({}, (err, results) => {
if (err) throw err
var images = []
for (var result of results) {
images.push(result.path)
}
res.render('profile', {
images: images
})
})
})
var server = app.listen(3030, function () {
console.log('Listening on port %d', server.address().port)
})
And in the views you should loop through the images to display them, i believe you are using handlebars so the view should be something like this :
<html>
<head>
<title>User Profile</title>
</head>
<body>
<h1>Welcome</h1>
{{#each images}}
<img src="{{this}}" height="180" width="250">
{{/each}}
</body>
</html>
Please Someone response me with what's wrong with this code...
When I run the program ,I find the bug in mongodb part.
The error in
var db = mongoclient.db();
var express = require('express'),
app = express(),
cons = require('consolidate'),
MongoClient = require('mongodb').MongoClient,
Server = require('mongodb').Server;
app.engine('html', cons.swig);
app.set('view engine', 'html');
app.set('views', __dirname + '/views');
var mongoclient = new MongoClient(new Server("localhost", 27017), {native_parser: true});
var db = mongoclient.db();
app.get('/', function(req, res){
// Find one document in our collection
db.collection('hello_combined').findOne({}, function(err, doc) {
if(err) throw err;
res.render('hello', doc);
});
});
app.get('*', function(req, res){
res.send('Page Not Found', 404);
});
mongoclient.open(function(err, mongoclient) {
if(err) throw err;
app.listen(8080);
console.log('Express server started on port 8080');
});
I'm only showing you this code because It shows how to connect to a database.
I didn't need that Server = require('mongodb').Server; section that you have.
The code shows how to
require monogodb to get the Driver for mongodb in Node. require("mongodb").MongoClient
then you connect using MongoClient.connect. In my case Im connecting to my allready existing database called crunchbase
then you can query the database I find the field with the name of category_code and the value biotech in the collection companies.
var MongoClient = require("mongodb").MongoClient;
MongoClient.connect("mongodb://localhost:27017/crunchbase", function(err, db){
console.log("connected to the DB");
var query = {"category_code" : "biotech"};
db.collection("companies").find(query).toArray(function(err, docs){
docs.forEach(function(doc){
console.log(doc.name + " is a " + doc.category_code + "company")
});
db.close()
})
})
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 trying to do simple update operation in mongodb. I have done it successfully using node.js, Express.js and Jade.js. Now I want to use restify.js in my existing application for rest api. but it is throwing "Express 500 Error: Argument passed in must be a single String of 12 bytes or a string of 24 hex characters"
This is my index.jade (form part):
form( method="get", action="/employee/:id/edit")
input(name="_id", type="hidden", value=employee._id.toHexString())
input(name="com", type="hidden", value=''+employee.comment)
input(name="titl", type="hidden", value=''+employee.title)
input(name="nam", type="hidden", value=''+employee.name)
input(id="edit", value="Edit", type="submit", class="btn btn-primary")
This is my employee_edit.jade:
form( method="post")
span.label My comment type is :
select(name='title')
- for (var i=0; i<2; i++)
if titl==arr2[i]
option(value=arr2[i], selected='selected')
=''+arr2[i]
else
option(value=arr2[i])
=''+arr2[i]
span.label My comment is for :
select(name='name', selectedInex=3)
- for (var i=0; i<22; i++)
if nam==arr[i]
option(value=arr[i], selected='selected')
=''+arr[i]
else
option(value=arr[i])
=''+arr[i]
span.label Comment :
textarea(rows='4', cols='50', name='comment', id='com')
=''+com
input(type="submit", value="Update")
This is my app.js file which is starting point of my application:
var express = require('express')
, routes = require('./routes')
, user = require('./routes/user')
, http = require('http')
, path = require('path')
, EmployeeProvider = require('./employeeprovider').EmployeeProvider
, myDate=require('date-utils');
var restify = require('restify');
var restServer = restify.createServer({ name: 'my-api' });
var app = express();
app.configure(function(){
app.set('port', 3333);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.set('view options', {layout: false});
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(require('stylus').middleware(__dirname + '/public'));
app.use(express.static(path.join(__dirname, 'public')));
});
app.configure('development', function(){
app.use(express.errorHandler());
});
var employeeProvider= new EmployeeProvider('localhost', 27017);
//Routes of express jade
//update an employee Feedback
app.get('/employee/:id/edit', function(req, res) {
employeeProvider.findById(req.param('_id'), function(error, employee) {
res.render('employee_edit',
{
//employee: employee,
empId: req.param('_id'),
com: req.param('com'),
titl: req.param('titl'),
nam: req.param('nam')
});
});
});
//save updated employee Feedback
app.post('/employee/:id/edit', function(req, res) {
employeeProvider.update(req.param('_id').toString(),{
title: req.param('title'),
name: req.param('name'),
comment: req.param('comment'),
created_at: new Date()
}, function(error, docs) {
res.redirect('/')
});
});
app.listen(3333);
I have written employeeprovider.js for mongodb connection:
var Db = require('mongodb').Db;
var Connection = require('mongodb').Connection;
var Server = require('mongodb').Server;
var BSON = require('mongodb').BSON;
var ObjectID = require('mongodb').ObjectID;
EmployeeProvider = function(host, port) {
this.db= new Db('node-mongo-employee', new Server(host, port, {safe: false}
{auto_reconnect: true}, {}));
this.db.open(function(){});
};
EmployeeProvider.prototype.getCollection= function(callback) {
this.db.collection('employees', function(error, employee_collection) {
if( error ) callback(error);
else callback(null, employee_collection);
});
};
EmployeeProvider.prototype.update = function(employeeId, employees, callback) {
this.getCollection(function(error, employee_collection) {
console.log('now in update'+employeeId);
if( error ) callback(error);
else {
employee_collection.update(
{_id: employee_collection.db.bson_serializer.ObjectID.createFromHexString(employeeId)},
employees,
function(error, employees) {
if(error) callback(error);
else callback(null, employees)
});
}
});
};
exports.EmployeeProvider = EmployeeProvider;
now by clicking edit button on index.jade it should open employee_edit.jade for editing employee. but it showing the error. address comes in address bar is:
http://localhost:3333/employee/:id/edit?_id=5215ad336ad5d6780d000001&com=dfsa&titl=Suggestion&nam=Abhishek
It works if i remove 8th and 9th line of app.js
var restify = require('restify');
var restServer = restify.createServer({ name: 'my-api' });
but i want to use restify in my app, what can i do???
thanx..!
After googling I found that, for all intents and purposes restify
and express can't coexist in the same node process, because for
unfortunate reasons, they both try to overwrite the prototype of the
http request/response API, and you end up with unpredictable behavior
of which one has done what. We can safely use the restify client
in an express app, but not two servers. so the "restServer" (declared in 8th and 9th line of app.js) can not be created in this app because we are having an express server which is listening on port 3333.