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
36 Comments
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)
Thanks! Your tutorial was a great starting point for me.
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!
[…] A example with Express and MongoDB (part 2) […]
Thanks so much!! Great!!
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?
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.
Thank you very much for this! Helped me alot!
Cool stuff!! 🙂
Cool!
Awesome tutorial! Thanks a bunch!
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.
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.
Make sure you have MongoDB up and running
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
});
});
});
On the “employee_edit.jade”file, change “[title]” for “editEmployee.title”.
thanks
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
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
Hey man,
Can you put part one back up? Its throwing a 404
It’s back up. Sorry about that.
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 🙂
It’s back up. Sorry about that.
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
Make sure mongo is up and running.
It was an awesome tutorial for a node.js , mongodb and express beginner.
Thanks for the write up..!!
Any ideas if you’d like to add a category?
What If I would want to have customers in the same app? How would I approach that? Many thanks
This is a very good tutorial. I learn lots of things from this site.
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
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
thanks for your tutorial
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
.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