- Overview
- Transcript
8.2 Adding JavaScript
JavaScript is a wonderful tool, and we'll write some JavaScript code to make deleting things easier. We'll also use jQuery UI's autocomplete and date picker components to enhance the post create/edit forms.
1.Introduction2 lessons, 05:56
1.1Introduction00:57
1.2What You Need04:59
2.Managing Posts3 lessons, 38:13
2.1First Steps07:55
2.2Writing the Views08:26
2.3Adding Functionality by Testing21:52
3.Tag Management2 lessons, 27:29
3.1Editing and Deleting Tags13:40
3.2Creating Tags13:49
4.Storing Data3 lessons, 47:22
4.1Setting Up the Dependencies17:58
4.2Implementing the Post Repository15:23
4.3Writing the Tag Repository14:01
5.Testing Functionality2 lessons, 33:06
5.1Testing the Post Functionality21:56
5.2Testing the Tag Functionality11:10
6.User Management3 lessons, 1:11:48
6.1Editing and Deleting Users25:19
6.2Creating Users21:53
6.3Managing a User's Roles24:36
7.Security and User Authentication2 lessons, 34:17
7.1Logging In and Out16:18
7.2Securing Our Application17:59
8.Enhancing the User Experience2 lessons, 36:38
8.1Incorporating a Menu19:51
8.2Adding JavaScript16:47
9.The Front-End2 lessons, 36:01
9.1Displaying the Published Posts24:37
9.2Paging Posts11:24
10.Conclusion1 lesson, 01:22
10.1Conclusion01:22
8.2 Adding JavaScript
Our next order of business is to write some JavaScript to enhance the user experience. And we're going to start with the delete links for the Index views of our posts, our tags, and our users. So let's first create a folder at the root of our project. This is going to contain our JavaScript files. So I'm just going to call this JS, but you can call it whatever you want to. And I'm also going to add some existing files. I have the jQuery library, version 2.1.1, then I also have jQuery UI version 1.11.1. Now you could use a CDN if you wanted to, but I prefer to use my own version, or at least my own copies of those because I like to be in control as to where the files that I use within my application are coming from. So we have these two files, let's add our own JavaScript file, and let's call it admin. Now, one of the nice things about our delete links is that they are all uniform. The only difference is the values of their href attributes. So we should be able to write the same JavaScript code and reuse it to through all of our views. And so the first thing we need to do is identify those links that are for deleting something. And we can do that with a custom data attribute. So we could say that for every a-element that has an attribute of data-action=delete, then that is a delete link and we want handle the click event. So, we have a function for handling that event. And the first thing we want to do is call the prevent default method. Because we want to prevent the default behavior of this link, and that is navigating to whatever is specified within the href attribute, because we want to inject our own behavior here. So, we prevent the default behavior and then we want to ask the user, are you sure that you want to delete this thing? So, we can have an if statement, if not, confirm, and then, are you sure you want to delete, and you know, we could specify what it is that they are deleting. So, let's, create another variable called value. We are going to add another data attribute to our links that's going to contain the value of whatever it is that we are deleting. So like for a post it, will be the title. For a user, it will be the username, and for a tag, it will be the tag. So, we could use this.getattribute, now we could use jQuery's API and wrap this around the jQuery function, but there's really no sense in doing that because we had the dom object already. We just need to call the .getattribute method and data-value. And then we can use that value in our question. Are you sure you want to delete this value? And if they cancel out, then we just return. But if they click OK or yes, then we continue on. So, now we just need to make a request. So, we're going to make a post request to whatever's specified within that href attribute. And we should also include the anti forgery token because each of the delete action methods are going to verify that token. That's easy enough to do because we can add that anywhere in any view. We just need to get the value in JavaScript. So let's create a variable called token. And we will get this value by specifying input, and then the name of this input element is __RequestVerificationToken, and then we want to call the val method to retrieve that value. And so whenever we make our post request, we will have a field with a name of __RequestVerificationToken, and its value will be our token, and then we need a callback function, and all we are going to do is simply reload the page. So if everything goes to plan, then whatever it is that they deleted is not going to be listed there. And that should be it. So now, we need to go to the index views. Actually, first of all, we need to go to the admin layout page, and we need to add references to these JavaScript files. So let's go to areas, let's go to the shared folder, and open up AdminLayout. And then we are going to add those JavaScript files by simply dragging and dropping them. I'm going to put them at the bottom of the body. So there is jQuery, there is jQuery-ui, and then finally the admin.js. And so now we can go to the index views for user, for tag, and for post. And we need to add the anti-forgery token in each one of these views. So, it doesn't matter where, but we preferably don't want to do it inside of the table. So here, AntiForgery.GetHtml, and we will use that in all of the other index views. Once again, outside of the table, other than that it doesn't matter where we put it, and there we go. Now all we need is to add the data-action attribute, and the data.value attribute to the delete link. We do that by passing another anonymous object to the ActionLink method, and here we have the data_action. The reason why it's underscore is we can't have a valid identifier with dash. But the MVC framework is going to automatically change it to data-action and that is equal to delete and then we need that data-value equal to our username in this case. So item.username and I put that in totally the wrong place. So let's grab that code out. We need a closing curly brace there. And then we will paste that object in. So we'll basically need to do the same thing in the other views. So let's go to the other one. Let's see, this one is for tags. So we will hit comma and then paste that in. The value in this case is just our item and then we will go to the post index. Let's scroll down, and comma pasting that in. Now in this case, we want the item.title and that should be that. So let's test it, let's run this application. So let's login as admin because admin has the ability to do everything, and then we will start testing these delete links. So here we are at the index for our users. Let's click on the delete link for this Foo user. We will be prompted to delete them. If we click Cancel, then nothing happens of course. But if we click OK, then it should delete that user, and it does. So deleting our users does work. So let's go to tags, and we have three tags. Let's delete the Tag-1-2. So we will click on Delete. If we click on OK then it should delete that tag and there we go. So let's go on to posts. And let's delete the second post. We will once again be prompted. If we click OK, that post is deleted. Now the second thing that we need to work on is the editing and creating of a post. If we go to the edit of this, we see that we have these tags, but we know that we have more tags that we could work with. And it will be nice to have some autocomplete here. And jQuery UI does have an autocomplete component, so we can use that in conjunction with modifying our tags controller to return a json structure of our tags. So let's close some files first of all, we don't need these index views open any longer, and let's go and open up our tag controller. And we want to modify the index action method. If we are making a request through AJAX, then we are going to have an accept header with application/json or at least that will be one of the accept types. So we can add some checks to this index action method. That if that is part of the accept types, then we will return json, otherwise we will return our normal view. So let's add an if statement. If request.AcceptTypes.Contains, and this is application/json. Then we want to return our tags as json formatted data. So return json, we need to pass in tags, but then we also need to specify the The json request behavior. Because the default behavior is to deny get requests. In this case it really doesn't matter, because we don't have any sensitive data or anything that could cause harm. So. We want to allow get in this case, otherwise we need to return the view, but I don't see any security checking here. Let's look at the top. Yes. We added the authorize attributes at the very top of this controller specifying that the roles have to be admin and editor. It's going to be a problem here because authors should be able to get our list of tags as json formatted data. So we're going to have to modify what we have. So let's copy this. And let's just say that we have to be authorized to get to this tag controller. And inside of the index action method we need to add a check to see if the user is in the author role. So if user.IsInRole author, then we want to say that that user Is not authorized. So return new HttpUnauthorizedResult. Otherwise then we return the view pressing in the tags. Now for the edit, we can go ahead and we can specify authorize and then add in the roles here because editing should not be allowed for authors. The same thing for deleting as well. So let's add the authorize attribute to those action methods. Now, the JavaScript for the auto complete is a little bit more complicated than the code that we wrote for the delete links. So I'm going to paste that code in. And the majority of that code is actually from From the jquery UI website. They have several examples, and I took one and lightly modified it. But before we do that, let's go to our create and our edit views. Let's also look at the index view because I know that we created this _PostLayout page, and index uses it edit and create. Now my original thought was to have a layout page for each individual section so that the posts would have their own layout page. The users would have their own, and tags would have their own, but it turned out that that's really not the case. So I'm going to change the index view to use the _AdminLayout page. And then I'm going to keep the create and edit views, using the _PostLayout page. And I will paste the JavaScript code inside of _PostLayout. That way, only those views have the JavaScript that they need and that's not going to be inside of any other view. So, let me paste that code in and as I said, this is mostly what you would find on the jQuery UI website. The big difference is that I have this available tags. And inside of the auto complete method, there's an option for the source. And I first checked to see if there's anything in the available tags variable. If it's undefined or if it's null or falsey, then a request is made to admin/tag to retrieve the tags in json formatted data, we assign available tags to that, and then available tags as used as the data source for the auto complete. And I think everything else is mostly left unchanged. So, let's save this. Let's run it, and let's log in as admin once again. Although we end of up with an error here, and it says that a shadow copy of the file already exists. Usually when this happens, if you just run it again then everything works. Like that. So let's log in as admin and let's first go to our tags. Now we have one tag called another tag. So we don't have much to work with right now. But let's go ahead and go to posts. And whenever we click on edit, we should be able to add in some other things, and then we can test the auto complete. Except that we have an error. It says that $ is undefined. So we're probably seeing this because the code for our auto complete is in the document before our references to jQuery. In fact, that's really the only reason why that would be there. So, looking at the source code does indeed verify that. So, This should be easily fixed. Let's go to the _AdminLayout, and we would simply add in a section called scripts. So, we will RenderSection scripts,and let's set required equal to false. And then we can go to _PostLayouts, and we can put all of this inside of the scripts section. So, @section, scripts and then we need the closing, curly brace after the script element. And that should do it. So let's go back to the browser. If we refresh, we should not get that error. And we don't. So if we hit comma here, we see that we are getting the auto complete but the styling leaves a lot to be desired. So let me grab some css and we're just going to use jQuery cdn. And let's paste this into admin_layouts at the top. So there is that. Let's go back, let's refresh, and then hopefully we will have some styling. It probably won't be pretty, well, it's okay. So we have another tag, let's do foo, bar, apple, and Microsoft. Actually we don't want apple here do we. No! Okay so we will submit, that's going to add those tags. So if we look at tags, that's what we have. So let's go to our posts. Let's create a new post. And This is a Tag Test. The slog we don't care about, the content we don't care about. The tags, though, if we start typing, we see that we have a foo, and then if we do indeed have our auto-complete. So we can at least see what tags are available. So we can use another tag, and if we just type in T, we should see the tags that have T in them. Now there's another tag in Microsoft. So now we have an autocomplete that makes adding existing tags to a post easy, but of course if we don't need those tags, then we can simply add in the tags that we do want. Our last enhancement is going to be for the Date Published field, because right now it's just a text field. It's not very user friendly for dates. So we can add a drop down date picker so that the user can easily pick what date that they want to publish their post. And this is going to be pretty easy to implement. First of all, we need to go to the view that has our form, or at least the partial view that has our form. That's _postform and we need to find the field for the published date, and there it is. Now we need to add and HTML attribute for the class which is already being done, but lets add another class here, lets call it date picker. And then we are going to use jQuery to select all of the elements that have a datepicker class, and use the datepicker component from jQuery UI. So let's go back to _postlayout and let's add another line of code. Where we call the jQuery function. Our css selector is the datepicker class. And we basically want to call datepicker. And that will give us a user-friendly date picker so that whenever we have focus on the Date Published field, like right now, we can simply just click on the date that we want for our published date. So now we're done with the administration portion of our application. All of the hard stuff is done. Now we just need to display that information for visitors, and we will do that in the next lesson.