In this recipe, we will take a look at how we can safely delete a record using a link. We will use jQuery to override the normal GET
functionality of a link and replace it with a POST
action. We will add a JavaScript confirmation to make sure they don't accidentally delete data. Also, because we can't guarantee that everyone is able to utilize JavaScript, we will provide an intermediary delete confirmation step.
In this recipe, we will build from the previous recipe where we created an intermediate delete confirmation page. The delete to intermediate "Are you sure?" page is great for folks who don't have JavaScript capabilities. However, why make those with JavaScript suffer? For that reason we will now make that initial Delete link take action.
We want to make sure that we don't use a GET
request to delete data though, as any spider crawling your site could delete your content (solved by adding security to your site). Also, we don't want our users to click Delete and have no chance to change their mind. To solve these two issues, we will use jQuery to override the GET
aspect of our Delete link and exchange it for a post direct to our delete logic. We will also add a confirmation pop-up to our link asking the user if they are sure they want to delete the specified resource.
ConfirmDelete
and Delete
view that do exactly what their names describe. All we need to do is jazz up the UI a bit. Let's start by adding a reference to jQuery in our master page.Views/Shared/Site.Master:
<script src="/Scripts/jquery-1.3.2.js" type="text/javascript"></script>
div
. We will give this parent div
a unique ID for the product that it is displaying by adding the ProductId
to its class
property. This will allow us to remove it from the display. Then we need to make the div
—that houses our delete link—easier to find in the same way, so that we can swap in a Deleting... message. We will also need to add a class to our delete links called delete
to make them easier to differentiate from other links on the page.Views/Home/Index.aspx:
<div class="container<%= p.ProductId %>"> <div class="busy<%= p.ProductId %>"> <%= Html.ActionLink("Delete", "ConfirmDelete", new {@id=p.ProductId}, new {@class="delete"}) %></div> //details for the product... </div>
indexContent
content area, we can add our <script>
tags. Then the first part that we want to add is our opening line of jQuery waiting for the page to load.Views/Home/Index.aspx:
<asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server"> <script> $(document).ready(...)
ready
function fires, we want to wire up a new function that will iterate through all of our delete links (using the link dot class name selector: a.delete)
to override our OnClick
event.Views/Home/Index.aspx:
<script> $(document).ready(function () { $('a.delete').click(...)
doDelete
variable for later use, where we can see if they want to delete the resource or not. Obviously, if they don't want to delete the resource we won't!Views/Home/Index.aspx:
$('a.delete').click(function () { var doDelete = confirm('Are you sure you want to delete this record?'), if (doDelete) { ... } else { return false; } }); });
ConfirmDelete
action name with Delete
(allowing us to bypass the confirmation view). Then we can split the URL into an array of strings on the forward slash character—at the end of which is the ProductId
that we are going to be working with. All of these values will be stuffed into conveniently named variables— url
, arr
, and id
.Views/Home/Index.aspx:
if (doDelete) { var url = this.href.replace('Confirm', ''), var arr = url.split('/'), var id = arr[arr.length - 1];
Views/Home/Index.aspx:
$('div.busy' + id).html("Deleting...");
.post()
method using our altered URL and passing in the ProductId
of the record we are deleting. We will also pass in a callback function, allowing us to capture when the record is actually deleted.Views/Home/Index.aspx:
$.post(url, '', function () {...}
hide()
on the div
containing our record, but that is generally too abrupt on the user experience. Instead, we will animate the record into oblivion using the animate()
method from the div
selector. Once the div
has been animated away, we will hide it for good measure.Views/Home/Index.aspx:
$.post(url, '', function () { $('div.container' + id).animate({ opacity: 0.25, left: 'toggle', height: 'toggle' }, 1000, function () { $('div.' + id).hide(); }); });
href
after doing all this work. For that reason, we will add one more line returning false
to the link, stopping its execution entirely.Views/Home/Index.aspx:
return false; }
Views/Home/Index.aspx:
<script> $(document).ready(function () { $('a.delete').click(function () { var doDelete = confirm('Are you sure you want to delete this record?'), if (doDelete) { var url = this.href.replace('Confirm', ''), var arr = url.split('/'), var id = arr[arr.length - 1]; $('div.busy' + id).html("Deleting..."); $.post(url, '', function () { $('div.container' + id).animate({ opacity: 0.25, left: 'toggle', height: 'toggle' }, 1000, function () { $('div.' + id).hide(); }); }); return false; } else { return false; } }); }); </script>
In this example, we are simply adding functionality with Ajax rather than being totally reliant on it. This means that whether the user has JavaScript or not won't matter. If they have it, their experience will be enhanced. But more importantly, if they don't have it they won't lose any functionality.
This is primarily done by using jQuery selectors and overriding existing events. Once we have our hooks into the HTML elements that we need, the sky is the limit as to what we can do.
This recipe was originally inspired by Phil Haack's awesome blog—haacked.com. Check it out here for more details as to why you might want to post to instead of get a delete
method:
http://haacked.com/archive/2009/01/30/simple-jquery-delete-link-for-asp.net-mvc.aspx.
One of the most important reasons for posting a form to perform a delete is that when a spider comes through your site performing gets on every link it finds, your data doesn't accidentally get deleted each time a crawl is performed!