Prash's Blog

Sticky Notes App in Nodejs using MongoDb May 16, 2012

Filed under: Nodejs — prazjain @ 4:10 pm
Tags: , , , ,

In this example we will see the interactivity between MongoDB and Nodejs.

We will create a “Post It” / “Sticky Notes” application in Nodejs and save the data in MongoDb.

Please check the other post for setting up mongodb with nodejs for this example..

Install npm packages for express, ejs, async :

npm install express ejs async

Now if you have followed back from the first article, then add the following methods to postitdb.js


// create the schema
var PostItSchema = new Schema(
{
	ts : { type: Date, default: Date.now },
	author : String,
	note : String
});

// register the schema
mongoose.model('PostIt',PostItSchema);

// create instance of the model
var Note = mongoose.model('PostIt');
exports.emptyNote = { "_id": "", author: "", note:""};

// define and export the add function to add a new note
exports.add = function(author, note, callback)
{
	var newNote = new Note();
	newNote.author = author;
	newNote.note = note;
	// to save a new note all you need to do it call save on it
	newNote.save(function(err)
	{
		if (err)
		{
			util.log('FATAL ' + err);
			callback(err);
		}
		else
		{
			callback(null);
		}
	});
};

// define and export the delete function
exports.delete = function(id,callback)
{
	// find the note by id then delete it by calling remove
	exports.findNoteById(id, function(err,doc)
	{
		if(err)
		{
			callback(err);
		}
		else
		{
			util.log(util.inspect(doc));
			doc.remove();
			callback(null);
		}
	});
};

// define and export the edit function
exports.edit = function(id, author, note, callback)
{
	// fine the note by id and edit it then save the changes.
	exports.findNoteById(id, function(err, doc)
	{
		if (err)
		{
			callback(err);
		}
		else
		{
			doc.ts = new Date();
			doc.author = author;
			doc.note = note;
			doc.save(function(err)
			{
				if(err)
				{
					util.log('FATAL ' + err);
					callback(err);
				}
				else
				{	
					callback(null);
				}
			});
		}
	});
};

// define and export allNotes function
exports.allNotes = function(callback)
{
	// we will get all notes from the db if we do not give any conditional expression
	Note.find({}, callback);
};

// define and export forAll function
exports.forAll = function(doEach, done)
{
	// we will get all notes from the db if we do not give any conditional expression
	// then invoke doEach function on every row
	Note.find({}, function(err, docs)
	{
		if(err)
		{
			util.log('FATAL ' + err);
			done(err,null);
		}
		docs.forEach(function(doc)
		{
			doEach(null,doc);
		});
		done(null);
	});
};

// define findNoteById and exports it.
var findNoteById = exports.findNoteById  = function(id, callback)
{
	Note.findOne({_id: id} , function(err,doc)
	{
		if (err)
		{
			util.log('FATAL ' + err);
			callback(err,null);
		}
		callback(null,doc);
	});
};

Now lets create app.js which holds all the logic for routing and connecting different bits to each other.

var util = require('util');
var url = require('url');
var express = require('express');
var postitdb = require('./postitdb');
var app = express.createServer();
app.use(express.logger());
app.use(express.cookieParser());
app.use(express.bodyParser());
app.register('.html',require('ejs'));
app.set('views',__dirname + '/views');
app.set('view engine','ejs');

var parseUrlParams = function(req,res,next)
{
	req.urlP = url.parse(req.url,true);
	next();
}

var checkAccess = function(req,res,next)
{
	// a logged-in user will have "AOK" set in his cookies
	if (!req.cookies || !req.cookies.notesaccess || req.cookies.notesaccess !== "AOK")
	{
		res.redirect('/login');
	}
	else
	{
		next();
	}
};

postitdb.connect(function(error)
{
	if (error) throw error;
});

app.on('close', function(errno)
{
	postitdb.disconnect(function(err) {} );
});

app.get('/', function (req,res) { res.redirect('/view'); } );

app.get('/login', function(req,res)
{
	res.render('login.html', { title: "Notes LOGIN" });
});

app.post('/login', function(req,res)
{
	if (req.body.username== "gabbarsingh" && req.body.pwd=="kalia")
	{
		res.cookie('notesaccess','AOK');
		res.redirect('/view');		
	}
	else
	{
		util.log('Cannot match username and password');
	}
});

app.get('/view', parseUrlParams, checkAccess, function (req,res)
{
	postitdb.allNotes(function(err, notes)
	{
		if(err)
		{
			util.log('ERROR ' + err);
			throw err;
		}
		else 
		{
			res.render('viewnotes.html', { title : "Notes", notes: notes });
		}
	});
});

app.get('/add', parseUrlParams, checkAccess, function(req,res) 
{
	res.render('addedit.html', { title : "Notes", postpath: '/add', note: postitdb.emptyNote});
});

app.post('/add', checkAccess, function(req,res)
{
	postitdb.add(req.body.author, req.body.note, function(error)
	{
		if (error) throw error;
		res.redirect('/view');
	});
});

app.get('/del', parseUrlParams, checkAccess, function(req,res)
{
	postitdb.delete(req.urlP.query.id, function(error) 
	{
		if(error) throw error;
		res.redirect('/view');
	});
});

app.get('/edit', parseUrlParams, checkAccess, function(req,res)
{
	postitdb.findNoteById(req.urlP.query.id, function(error, note) 
	{
		if (error) throw error;
		res.render('addedit.html', {title : "Notes", postpath:'/edit', note: note });
	});
});
app.post('/edit', checkAccess, function(req,res)
{
	postitdb.edit(req.body.id, req.body.author, req.body.note, function(error)
	{
		if (error) throw error;
		res.redirect('/view');
	});
});
app.listen(3000);

Now we just need to give html files for rendering the output.
Create a views directory that will be used by ejs to render html from html files from this directory as registered earlier.

mkdir views

Create all the html files mentioned below in “views” directory.
layout.html

<html>
	<head><title><%= title %></title></head>
	<body>
		<h1><%= title %></h1>
		<p><a href='/view'>View</a> | <a href='/add'>Add</a></p>
		<%- body %>
	</body>
</html>

viewnotes.html

<table><% notes.forEach(function(note) 
{ %>
	<tr><td>
			<p><%= new Date(note.ts).toString() %>: by <b> <%= note.author %></b></p>
			<p><%= note.note %></p>
		</td>
		<td>
			<form method='GET' action='/del'>
				<input type='submit' value='Delete'/>
				<input type='hidden' name='id' value='<%= note._id %>' />
			</form>
			<br/>
			<form method='GET' action='/edit'>
				<input type='submit' value='Edit' />
				<input type='hidden' name='id' value='<%= note._id %>' />
			</form>
		</td>
	</tr>
<% }); %></table>

addedit.html

<form method='POST' action='<%= postpath %>'>
	<% if(note) 
	{ %>
		<input type='hidden' name='id' value='<%= note._id %>' />
	<% } %>
		<input type='text' name='author' value='<%= note.author %>' />
		<br/>
		<textarea rows=5 cols=40 name='note'>
		<%= note.note %>
		</textarea>
		<br/>
		<input type='submit' value='Submit' />
</form>

login.html

<form method='POST' action='/login'>
	<p>Click the <i>Login</i> to log in.</p>
	<table>
		<tr>
			<td>Username: </td>
			<td><input type='text' name='username' length=30 /></td>
		</tr>
		<tr>
			<td>Password: </td>			
			<td><input type='password' name='pwd' length=30 /></td>
		</tr>
		<tr>
			<td><input type='submit' value='Login' /></td>
			<td><input type='reset' value='Clear' /></td>
		</tr>
	</table>
</form>

That is all you need, and now you can run the application using

node app

And visit the url : http://localhost:3000, Voila!

About these ads
 

2 Responses to “Sticky Notes App in Nodejs using MongoDb”

  1. gildean Says:

    Nice tutorial!
    One error tho’:
    on line 80 of app.js “note: notesdb.emptyNote” should be “note: postitdb.emptyNote”.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
Follow

Get every new post delivered to your Inbox.