Save and Delete Content in Express with HTTP Verbs

Share this video with your friends

Social Share Links

Send Tweet
Published 9 years ago
Updated 5 years ago

In this lesson you will learn how to support data modification by handling HTTP verbs besides GET. We will look at how to edit, save, and delete content with .put and .delete.

[00:00] In addition to serving data and pages, Express also supports other HTTP verbs besides Get that will let you actually modify data. To show that, we have updated our user name route here, and we've now got a Res.render call that is going to pass in a user object and an address object.

[00:21] We have updated our template so that we've got a nice little link back to the list of users, we've got the profile picture was we are going to use -- the medium one now, and we've got a couple of links there, edit and delete. Then below that, in our actual content, we've got a definition list.

[00:43] In that list, you'll see that you have two DD tags for each aspect of the address, one that just displays the data, and the other one that actually has an input tag in it. Essentially, that's going to let us do some in-place editing.

[00:59] This is what our template looks like in the browser. If we come back here and we actually look at our "Edit" link, the edit link calls an edit function.

[01:12] What the edit function does is, it's going to show everything that has a class of in it, and hide everything that has a class of view, and we've got a cancel function here that does just the opposite. Those two functions are what let us toggle between the in-place editing and just the regular view.

[01:31] If we click on edit, we get the edit form. If we click "Cancel," it'll get rid of that foreman just go back to displaying the data. Where we actually get into modifying data is the say function, so when we click on the "Save" button, it's going to call this save function.

[01:47] This is just going to call to the path that matches our user name that we're looking at now. Then, the important part here is the method property, which is set to put, so that's going to do an HTTP put, and it's going to send this data back. That's just the value of all those input fields that we have, and then finally when the call returns, it's going to call this complete call back, which is going to cancel.

[02:15] It's going to call cancel, which is really just getting rid of our edit form, and that we are going to reload the page so that we can see the new data loaded into the browser there. Now, if we go to our page and open the edit form and hit save, it's going to refresh.

[02:32] But if we look at the terminal here, we can see that we actually got some error output. That's because we're not actually handling that put verb, and in order to handle it in a meaningful way, we actually need to go install something called body parser, which is going to let us do exactly what it sounds like and parse the body of the request.

[02:56] We are going to require that package in here, in our file, so we've got a property called BodyParser now. We're going to configure our application to use it. So then, we're going to say App.UseBodyParser.URL encoded, because our data is going to be URL encoded by the form, by default.

[03:19] Then extended true is just telling it to do all the parsing that it can. And then, we can come down here and actually define our Put handler. So, App.Put this time instead of App.Get, still using the same username mount path. Then what we're going to do is we are going to pull off that username like we have before.

[03:43] We're going to get that user's data, using a little utility function that we've got in here, and then we are going to say User.Location equals Request.Body. So, Request.Body is going to be this data object that is getting passed back from our form, and we're just going to set that onto our user object directly, and then we're going to call SaveUser, which is essentially just going to rewrite that file back out.

[04:10] Then we're going to end the request by saying Response.End. If we start our dev circuit back up, we can go back to the browser and we'll refresh this page, and then go ahead and initiate an edit, and then we will change Alan's address to be New York, California.

[04:29] Then we'll hit "Save," and you can see that the page did refresh there, and we can even, just to show that it works, we can go back to the user's list, come back to Alan, and we see that he does have that address. We can go look at our JSON file here and see that it was written out to that file.

[04:48] The last type of action we're going to implement here is a delete. So we've got a delete link, which calls this function called DEL, you've always got to be careful about naming things delete on the client side, because it's a reserved word.

[05:01] But this function is going to call, again, the same username URL. But this time, the method is going to be set to delete. We don't need to send any data with it, but when the call is complete, we're just going to go back to the route pass, so we're going to go back to our list of users.

[05:19] If we go back into our express code, we can define an app.delete this time, and give it that same username "Path." This time, we are going to get the path to that user's file, and delete that file. Then we're going to send back a 200 status letting the client know that the request completed successfully.

[05:42] If we go here and click "Delete," it's going to take us back, but we still see Alan in the list there. If we try and click on him, we're going to get an error because that file is not actually there. We can't load the data. The reason for that is that we are loading this list of users when the application starts up, and then we're just serving it from the route.

[06:07] There's no way for that data to be reloaded while the app is running. What we actually need to do is we'll go up and delete this code that runs at app startup, and right here within the route handler we're just going to paste in some code that will define our users array.

[06:24] We're going to read the users directory, so it's going to get all the files that are actually in that directory. We'll loop over the files, we'll read them in and we'll parse out the data, set the full name they have been using, push that user object back into our array, and then once we know that we have the right amount of users defined or loaded, then we'll go ahead and render that index page.

[06:52] We can go back and refresh. If we go into Daryl here and say, "Delete," it takes us back to that list, and you can see Daryl is in fact missing from the list.

Martin
Martin
~ 8 years ago

I'm sure if it's deliberate, but it's like you skipping over the part surrounding the getUser function. I seems straightforward, but there's no real description to the change from the list to the actual user files. At least not what I can see.

Ben Clinkinbeard
Ben Clinkinbeardinstructor
~ 8 years ago

Woah, you're right. Sorry about that!

Vishwas Chouhan
Vishwas Chouhan
~ 8 years ago

The tutorials going great but missing out on the utility functions and how they handling data throws me off and I can't follow as I am trying to build the app following the video.

Stefan
Stefan
~ 8 years ago

Hey, i found one problem if i start my server with "npm dev" from your previous lectures, not load a user picture because server restarting and not return picture. Do you have a solution about it ?

Ben Clinkinbeard
Ben Clinkinbeardinstructor
~ 8 years ago

Hi Stefan,

I'm not seeing that issue.What action in the app is causing the server to restart? If it's editing a user, one thing you could try is changing the dev script to tell nodemon to ignore the users directory. nodemon index.js --ignore users/.

Hope that helps, Ben

Stefan
Stefan
~ 8 years ago

Thanks for your answer, now this working good.

Jaclyn
Jaclyn
~ 8 years ago

I agree! I like the project & am learning how routing works but there are some roadblocks that might not be necessary for the learning to keep moving forward.

The comment was 7 months ago so I'll just reiterate... I am constantly having to go to the github repo to see what functions were being built or refactored. It's a good practice in reading the code and seeing what's happening when but a detriment in following the video. WRiting the code with you in the video is not sufficient because there are gaps in what is being built and what is shown. A short heads up on 'so I built this getUser function to fix this problem' would be super helpful. Same thing with the users photos - I didn't clone the repo for this lesson down because I wanted to start from scratch to learn so it would be helpful to have a heads up and say, 'hey, get a collection of photos that you want to use so you can learn to display photos with your user'

Joel
Joel
~ 7 years ago

The packaged version of nodemon in the repo only watches js by default, but I ran a more recent nodemon (because didn't clone the repo) where nodemon watches .json as well by default, so I had the same issue as Stefan reported of nodemon restarting when .json files where modified or removed.

The workaround nodemon index.js --ignore users/ didn't work for me though, nodemon seems to want the --watch flag to watch a file, so: nodemon --watch index.js. Or nodemon --ignore users/ or nodemon --ignore .json would work as well.

George Katsanos
George Katsanos
~ 7 years ago

Exactly what Jaclyn said. I admit I am rather disappointed as the cost of the yearly subscription is rather high compared to other online courses (codeschool) which are much more paced and allow following the course without having to pause/copy code from github/resume.. For example, where's the explanation about require('path') ? .. Any mention about the saveUser() function? If I wanted to copy/paste code I wouldn't buy an online video learning subscription. :(

~ 7 years ago

Agreed. Steps being skipped over is very irritating.

Benjamin
Benjamin
~ 7 years ago

how are we able to use jquery in the handlebars template? i don't remember ever adding it?

Anett_Soos
Anett_Soos
~ 6 years ago

agreed! skipping steps is not cool, I completely lost what is going on. I wish it was addressed and more videos put in as I just give up at this point.

Cuong
Cuong
~ 6 years ago

Yes there are some steps being skipped in the video. I am trying to build as a watch the video and there is a problem with my code. Please help!

The normal Handlebars list of users loads like it is supposed to but when I try to click on a person to get their detailed profile I get the following error after adding these two functions (which was not explained in the video, I had to look at the gitHub code):

Functions added or changed:

function getUserFilePath (username) { return path.join(__dirname, 'users', username) + '.json'; }

function getUser (username) { var user = JSON.parse(fs.readFileSync(getUserFilePath(username), {encoding: 'utf8'})) user.name.full = _.startCase(user.name.first + ' ' + user.name.last) _.keys(user.location).forEach(function (key) { user.location[key] = _.startCase(user.location[key]) }) return user }

app.get('/:username', function (req, res) { var username = req.params.username var user = getUser(username) res.render('user', { user: user, address: user.location }) })

ReferenceError: path is not defined at getUserFilePath (C:\Users\Cuong\Documents\GitHub\Learning-Express\index.js:9:3) at getUser (C:\Users\Cuong\Documents\GitHub\Learning-Express\index.js:13:41) at C:\Users\Cuong\Documents\GitHub\Learning-Express\index.js:51:14 at Layer.handle [as handle_request] (C:\Users\Cuong\Documents\GitHub\Learning-Express\node_modules\express\lib\router\layer.js:95:5) at next (C:\Users\Cuong\Documents\GitHub\Learning-Express\node_modules\express\lib\router\route.js:137:13) at Route.dispatch (C:\Users\Cuong\Documents\GitHub\Learning-Express\node_modules\express\lib\router\route.js:112:3) at Layer.handle [as handle_request] (C:\Users\Cuong\Documents\GitHub\Learning-Express\node_modules\express\lib\router\layer.js:95:5) at C:\Users\Cuong\Documents\GitHub\Learning-Express\node_modules\express\lib\router\index.js:281:22 at param (C:\Users\Cuong\Documents\GitHub\Learning-Express\node_modules\express\lib\router\index.js:354:14) at param (C:\Users\Cuong\Documents\GitHub\Learning-Express\node_modules\express\lib\router\index.js:365:14) at Function.process_params (C:\Users\Cuong\Documents\GitHub\Learning-Express\node_modules\express\lib\router\index.js:410:3) at next (C:\Users\Cuong\Documents\GitHub\Learning-Express\node_modules\express\lib\router\index.js:275:10) at SendStream.error (C:\Users\Cuong\Documents\GitHub\Learning-Express\node_modules\serve-static\index.js:121:7) at emitOne (events.js:116:13) at SendStream.emit (events.js:211:7) at SendStream.error (C:\Users\Cuong\Documents\GitHub\Learning-Express\node_modules\send\index.js:270:17)

My gitHub code for reference if needed: https://github.com/cu0ngpitt/Learning-Express/blob/Http-Verbs/index.js

Andy Elion
Andy Elion
~ 5 years ago

Bug in app.put method, should be

app.put('/:username', function (req, res) { var username = req.params.username var user = getUser(username) user.location = req.body.location saveUser(username, user) res.end() })

Markdown supported.
Become a member to join the discussionEnroll Today