A Sample App with Node.js, Express and MongoDB – Part 2

In my last post, we created a simple Employee database using Node, Express and MongoDB. In this tutorial, we’ll add the ability to edit and delete employees.

Edit an Employee

The first thing we need to do is add additional functions to employeeprovider.js.

employeeprovider.js

//find an employee by ID
EmployeeProvider.prototype.findById = function(id, callback) {
    this.getCollection(function(error, employee_collection) {
      if( error ) callback(error)
      else {
        employee_collection.findOne({_id: employee_collection.db.bson_serializer.ObjectID.createFromHexString(id)}, function(error, result) {
          if( error ) callback(error)
          else callback(null, result)
        });
      }
    });
};

// update an employee
EmployeeProvider.prototype.update = function(employeeId, employees, callback) {
    this.getCollection(function(error, employee_collection) {
      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)       
					});
      }
    });
};

The function findById will be used to retrieve employee data from our database based on ID. You’ll see this put into use when we edit our index view with an Edit button. The function update does exactly what it says, it updates the employee data in our database. Next we’ll add new routes to app.js.

app.js

//update an employee
app.get('/employee/:id/edit', function(req, res) {
	employeeProvider.findById(req.param('_id'), function(error, employee) {
		res.render('employee_edit',
		{ 
			employee: employee
		});
	});
});

//save updated employee
app.post('/employee/:id/edit', function(req, res) {
	employeeProvider.update(req.param('_id'),{
		title: req.param('title'),
		name: req.param('name')
	}, function(error, docs) {
		res.redirect('/')
	});
});

Again, the link we will add to our index view will use the get method. As you can see, it receives an _id parameter and calls the findById function we just created in employee provider.js. Later, we’ll create the employee_edit view to display the edit form. The post method calls the update function and redirects the user back to the index view.

employee_edit.jade

extends layout

block content
    h1= "Edit Employee"
    div.newemployee
        form( method="post")
            input(name="_id", type="hidden", value=employee._id.toHexString()) 
            div
                div
                    span.label Title :
                    input(type="text", name="title", id="editEmployeeTitle", value=[title])
                div
                    span.label Name :
                    input(type="text", name="name", id="editEmployeeName", value=employee.name)
                div#editEmployeeSubmit
                    input(type="submit", value="Update")
        a(href="/")!= "Back to Employee List"

index.jade

extends layout

block content
    h1= title
    #employees
        - each employee in employees
          div.employee
            div.created_at= employee.created_at
            div.title= employee.title 
            div.name= employee.name
                form( method="get", action="/employee/:id/edit") 
                    input(name="_id", type="hidden", value=employee._id.toHexString()) 
                    input(id="edit", value="Edit", type="submit")
        a(href="/employee/new")!= "Add New Employee"

We’ve added an Edit button to our index view that will call the get method we just created in app.js. The get method will then render the employee_edit view and the form post will update the employee. That is the bare bones minimum needed to update an employee in MongoDB.

Delete an Employee

Next, we’ll writes the methods necessary needed to delete an employee from MongoDB.

employeeprovider.js

//delete employee
EmployeeProvider.prototype.delete = function(employeeId, callback) {
	this.getCollection(function(error, employee_collection) {
		if(error) callback(error);
		else {
			employee_collection.remove(
				{_id: employee_collection.db.bson_serializer.ObjectID.createFromHexString(employeeId)},
				function(error, employee){
					if(error) callback(error);
					else callback(null, employee)
				});
			}
	});
};

The delete function will accept an employeeId parameter and delete the employee from our employee collection.

app.js

//delete an employee
app.post('/employee/:id/delete', function(req, res) {
	employeeProvider.delete(req.param('_id'), function(error, docs) {
		res.redirect('/')
	});
});

We’ve added an delete route that will call the delete function we just created in employeeprovider.js. Now we can add a Delete button to our index view.

index.jade

extends layout

block content
    h1= title
    #employees
        - each employee in employees
          div.employee
            div.created_at= employee.created_at
            div.title= employee.title 
            div.name= employee.name
                form( method="post", action="/employee/:id/delete") 
                    input(name="_id", type="hidden", value=employee._id.toHexString()) 
                    input(id="delete", value="X", type="submit")
                form( method="get", action="/employee/:id/edit") 
                    input(name="_id", type="hidden", value=employee._id.toHexString()) 
                    input(id="edit", value="Edit", type="submit")
        a(href="/employee/new")!= "Add New Employee"

Clicking the “X” button will call the delete route and delete the selected employee from our employee collection. I left out the additional changes made to style.styl for employee_edit.jade but you should be able to retrieve them from the source code link below.

You can now re-run your application and navigate to localhost:3000.

node app.js

This is the conclusion of our Employee database CRUD application. You should now have a basic knowledge of how to utilize the Express module for Node.js along with how to create and utilize a collection in MongoDB. Leave any questions you may have in the comment section below. I’ve posted the source code on github so feel free to use and modify it however you want.

Source Code: https://github.com/ijason/NodeJS-Sample-App

NodeJSpt2SS1
NodeJSpt2SS2

36 Replies to “A Sample App with Node.js, Express and MongoDB – Part 2”

  1. Awesome tutorial. However when i go to employee/1/edit the next error comes in: 500 Error: Argument passed in must be a single String of 12 bytes or a string of 24 hex characters

    I think it has to do with the findById function in the employeeProvider.(I copy pasted to be sure it wasn’t my mistyping)

  2. Odd problem, but when I add employees and then try to edit them the edit page always retains the data of the most recenty added employee…if I start out with no employees it will keep ticking down.

    So say I add:
    Rufus -> Underling
    Rude -> Underling
    Sephiroth -> Boss

    The page will have Sephiroth’s info. If I delete him it changes to Rude’s, then Rufus regardless of any ID I pass the edit_employees page via HTTP GET.

    If however, I start/stop the server then it works fine.
    Next suppose I add
    Magus -> Underboss. The edit_employee page will retain Magus’ information in perpetuity. If I delete him the edit page will still show his information. This is quite strange, any help would be much appreciated, thanks! 🙂

    This is my first go with ExpressJS

    • I also found a similar bug. After some debugging the line that was causing it is in the following code:

      app.get(‘/employee/:id/edit’, function(req, res) {
      employeeProvider.findById(req.param(‘_id’), function(error, employee) {
      res.render(’employee_edit’,
      {
      title: employee.title,
      employee: employee
      });
      });
      });

      replace the title: employe.title and employee.employee with:

      app.get(‘/employee/:id/edit’, function(req, res) {
      employeeProvider.findById(req.param(‘_id’), function(error, employee) {
      res.render(’employee_edit’,
      {
      editEmployee: employee
      });
      });
      });

      then change the edit jade template to reflect this change and refer to editEmployee. This should fix the issue.

      • I think editing the passthrough would be a simpler fix…that way the template doesn’t need to change:

        app.get(‘/employee/:id/edit’, function(req, res) {
        employeeProvider.findById(req.param(‘_id’), function(error, emp) {
        res.render(‘employee_edit’,
        {
        employee: emp
        });
        });
        });

        Good catch though, that would’ve stumped me for hours!

  3. Pingback: Express.js | M's Web Dev

  4. I have just one problem. How do I connect to db once and maintain it if I have many collections and to make it simple they are in different files?

  5. i’m going to guess that it’s because the code has employee being passed in both as the key and value:

    employeeProvider.findById(req.param(‘_id’), function(error, employee) {
    res.render(’employee_edit’,
    {
    employee: employee
    });
    });

    so node is simply getting confused and always defaulting to whatever was first done in the session – i.e. your first edit. this would be why it’s ok again after you restart the server… but just the first time. i could be wrong, but it seems that – leaving the code as is – it’s always going to go with your first successfully completed edit for the life of the session.

    as anish pointed out, simply changing the key name and then editing the “employee_edit” view to reflect the change works fine.

  6. This is really an awesome tutorial, I followed the steps, and did not have much trouble making it work end to end.

    I like to do one enhancement to the sample project:
    How do I display the employee entries in a table format using jade?

    I could not find any useful and complete tutorial on jade on the internet.
    Thanks in advance.

  7. I have tried the code. The first tutorial was working fine for me. But this one is raising error in edit and delete are clicked. For delete : “Cannot POST /employee/:id/delete” and for edit: “Cannot GET /employee/:id/edit?_id=5209bdd462eebb9002000001” are the errors I am getting. Please help me.

  8. So, I have the issue where clicking the edit button sends the request and then it eventually times out, thus never displaying the edit form. I have made the above mentioned edits in the route, but still no dice.


    app.get('/employee/:id/edit', function(req, res) {
    employeeProvider.findById(req.param('_id'), function(error, emp) {
    res.render('employee_edit', {
    title.emp.title,
    employee: emp
    });
    });
    });

  9. Thank you very much. I tried to do something like that some months ago (before your post) and I failed. Now I understand more about express + node + mongoDB. Thanks!

    If I could ask you for something in your next post, could you make an example of using either google graphs or D3 to plot a graph? a good example could be: the number of employees inserted over the days… just to see how it works to pull an array from mongoDB and plot it.

    Thanks

  10. I really like this tutorial but the only problem i have is that my index page does not list my employees from the database so if you could help me fix that i will be glad.Thanks

  11. this looks great but I’d like to start with part 1, however the link is broken, error 404. would you be so kind as to make it available or post a link to part 1? much appreciated 🙂

  12. Here i got a error.

    TypeError: /Users/bigo_macmini/dev/mongo/EmployeeDB/views/index.jade:6
    4| h1= title
    5| #employees
    > 6| – each employee in employees
    7| div.employee
    8| div.created_at= employee.created_at
    9| div.title= employee.title

    Cannot read property ‘length’ of undefined
    at __jade.unshift.lineno

  13. i was facing this issue – “500 TypeError: Cannot read property ‘title’ of undefined…”
    i debugged this and replace
    _id : employee_collection.db.bson_serializer.ObjectID.createFromHexString(id)
    with
    _id : ObjectID.createFromHexString(id) // correct

    in “findById” function in ’employeeprovider.js’ file.
    thanx

  14. Hello,
    I run into the following when attempting to edit an entry.

    Cannot read property ‘_id’ of undefined

    I see from the incoming url that _id is being assigned a value.

    I also receive a similar error the variable

    employee.name

    I can bump past this by assigning numbers to the hidden field values in employee_edit.jade

    Thanks.

    Stephen

  15. Helpful blog post . For my two cents , if you is looking for a service to merge two PDF files , my business merged a tool here https://goo.gl/LgDZyW.

  16. Hello,
    I run into the following when attempting to edit an entry.

    Cannot read property ‘_id’ of undefined

    I see from the incoming url that _id is being assigned a value.

    I also receive a similar error the variable

    employee.name

    and also I run into the following when attempting to delete an entry

    entry can not be delete

Leave a Reply

Your email address will not be published. Required fields are marked *

Please Do the Math      
 

*