Practical ASP.NET
Deleting with jQuery and Web Services
Peter continues to extend his jQuery/jTemplate case study by supporting deletes of multiple rows with a single mouse click.
The seed for this column was an article that I did for Visual Studio Magazine ("
Integrating jQuery, Web Services, AJAX and ASP.NET"), which leveraged both AJAX for ASP.NET and jQuery to implement a CRUD page for customer data. Over the previous two columns ("
Defining Templates with jTemplate" and "
Updating From the Client"), I've extended the case study to display and update multiple orders for the customer. This column implements deletes on orders.
My previous work gave the user the ability to change multiple fields in multiple records and then send all the changes back to the server with a single button click. For deletes, the user should be able to delete multiple rows at once.
Extending the Template
The obvious solution is to provide a checkbox on each row in a column marked "Delete." The user could then check off the rows to delete and then press a "Delete" button to send the primary key fields for all checked rows back to the server for deletion. I'll need to create a Web Service that will accept an array of NorthwindOrder objects and delete each onem but that Web Service is so similar to the update service I created in last week's column, I'll skip over it (get the download if you want the code).
The next thing I need to change is my jTemplate template to add a "Delete" column. I keep my template in a separate file in the site called OrdersTable.htm. In the template, I add a new column to hold the checkbox and give the checkbox an id of "DeleteFlag":
{#foreach $T as ord}
‹tr›
‹td id="Delete"›
‹input type="checkbox" id="DeleteFlag" /›
‹/td›
‹td id="OrderId"›{$T.ord.OrderId}‹/td›
‹td id="ShippedDate"›
‹input id="Data" type="text"
value="{$T.ord.ShippedDate}" /›
‹/td›
‹/tr›
{#/for}
Next, I need to add an HTML button to my ASPX file, setting its caption to "Delete" and tying it to a routine that will process the rows marked as "to be deleted":
‹input id="DeleteButton" type="button" value="Delete"
onclick="return DoCustomerDeletes()" /›
Programming the Deletes
Finally, I need to create my DoCustomerDeletes JavaScript routine to do my updates. One caveat about this solution: jQuery is sufficiently flexible that there are probably a dozen ways to solve this problem. The solution that I've picked lets me demonstrate some jQuery functionality and is (I hope) reasonably easy to follow. Tune in next week, for instance, to see a different way to retrieve tablerows based on values in one of the row's tablecells.
I first set up an array to hold the objects to be passed back to the Web Service and a counter to keep track of where I am in processing the table. I also define a variable to hold any NorthwindOrder objects I might need:
function DoCustomerDeletes()
{
var ordDList = new Array();
var iD = 0;
var ord;
This jQuery returns all the elements with an id of "#Delete" that have their checked property set (i.e. the rows to be deleted). However, I need access to the checkbox's tablerow, so I retrieve the parent for the checkbox (the tablecell) and then its parent (the tablerow):
$("#Delete :checked").parent().parent().each(function() {
});
In my function that's called by the each function, I create a NorthwindOrder object, push it onto my array. I then find the cell with the id of "OrderId" and set the NorthwindOrder object's OrderId property to the innertTextProperty of the cell:
ord = new NorthwindOrder();
ord.OrderId = $(this).find("#OrderId")[0].innerText;
ordDList.push(ord);
After processing all of the tablerows, I check to see if I pushed anything onto my delete array and, if I did, I pass the array to my Web Service for processing:
if (ordDList.length › 0) {
NWCusts.DeleteCustomerOrders(ordDList, OrdersUpdated,
GenericFailure);
}
Finally, if all goes well, I need to retrieve the CustomerId for the currently selected customer and call my routine that retrieves and redisplays the customer's information (see the original article for the details):
var lb = $('#ctl00_MainPlaceHolder_ListBox1');
GetData(lb[0]);
If you do download the sample code for this column, you'll find that I've implemented the delete functionality twice. In addition to the solution that I've shown here, attached to the "Delete" button, I also integrated delete with the update code that I added in last week's column. The integrated version lets the user make any combination of updates to textboxes and flag records for deletion in the delete column and then press the "Update" button to have all of the changes made. With a little jQuery I've got three of CRUD operations implemented to give the user a more flexible interface and (as discussed in the earlier columns) a more scalable application. Next week: Inserts!
About the Author
Peter Vogel is a system architect and principal in PH&V Information Services. PH&V provides full-stack consulting from UX design through object modeling to database design. Peter tweets about his VSM columns with the hashtag #vogelarticles. His blog posts on user experience design can be found at http://blog.learningtree.com/tag/ui/.