Practical ASP.NET

Updating From the Client with jQuery

Peter continues to exploit jQuery in his client-side code to integrate an ASP.NET page with a WCF service -- this time to support updating data.

In an earlier article Integrating jQuery, Web Services, AJAX and ASP.NET, I integrated Web Services, jQuery, and ASP.NET to create a page that retrieved a single customer object and made it available for updating in a web page. Last week's column, Defining Templates with jTemplate, extended the case study in the article to display multiple sales orders for the customer (see Figure 1). This week, I'll add updates.

Figure 1. A Client-side generated table -- The table of sales orders allows the user to update multiple rows and submit all the changes simultaneously by clicking on the Update button.

Begin on the Server
My first step, as usual, is to add a method to the WCF service I created in the original article. This method accepts an array of NorthwindOrder objects, finds each corresponding object in an Entity Framework model of the Northwind database, and updates the ShippedDate. Using Entity Framework and LINQ isn't essential, but it does shorten my code.

‹OperationContract()› _
Public Function UpdateCustomerOrders(ByVal Orders As NorthwindOrder()) _
As String
Try
Dim entsNW As New northwndModel.northwndEntities
For Each ord As NorthwindOrder In Orders
Dim Aord = (From ordr In entsNW.Orders _
Where ordr.OrderID = ord.OrderId _
Select ordr).First

Aord.ShippedDate = ord.ShippedDate
Next
entsNW.SaveChanges()
Return "OK"
Catch ex As Exception
Return ex.Message
End Try
End Function
On the Client
In last week's column, I created a jTemplate template to facilitate generating my table of sales order data. To support updating, I've enhanced that template by adding id attributes to the table, the cells in the data rows, and the textbox within the cell. I also enclosed the column headers and data rows in thead and tbody elements:
‹table id="OrdersTable"›
‹thead›
‹tr›
‹td›Order Id‹/tD›
‹td›Shipped Date‹/td›
‹/tr›
‹/thead›
‹tbody›
{#foreach $T as ord}
‹tr›
‹td id="OrderId"›
{$T.ord.OrderId}
‹/td›
‹td id="ShippedDate"›
‹input id="Data" type="text"
value="{$T.ord.ShippedDate}" /›
‹/td›
‹/tr›
{#/for}
‹/tbody›
‹/table›
When the user clicks on the Update button, I need to create a set of objects and pass them to my service. First I declare a variable to hold one Order, an array to hold all the orders to be passed back to the server, and a counter to keep track of where the next order should go in the array:
var ord;
var ordList = new Array();
var i = 0;
There's probably a dozen ways to build my array of orders but, since each row in the table represents a single order, it made sense to me to use jQuery to retrieve a collection of all of the rows. In this example, my jQuery selector finds all the tr elements (the final element mentioned), but only if the tr element is inside a tbody element and, furthermore, only if that tbody element is inside whatever element has the id "OrdersTable". The each function that I call will execute the enclosed function once for every row I find:
$("#OrdersTable tbody tr").each(function() {
...create array of NorthwindOrder objects...
});
Within the enclosed function, I first create a NorthwindOrder object and set my ord variable to point to it. At this point the reference this will be pointing to the tr element currently being processed. I can use $(this) and jQuery's find function to search within the current tr element to retrieve all the td elements. When I finish this processing, I'll have set the properties on my NorthwindOrder object so I'll add it to the array that will be sent to my Web Service:
ord = new NorthwindOrder();
$(this).find("td").each(function() {
...set properties on ord...
});
ordList[i] = ord;
i++;
To set the properties on the NorthwindOrder object, I first check the id property of the td element. If it's the OrderId cell, I can just extract its innerText. For the ShippedDate cell, however, I need to do another find to retrieve the input element that contains the user's data. jQuery helps here again (as does assigning an id value of "Data" to the input element):
switch (this.id) {
case "OrderId":
ord.OrderId = this.innerText;
break;
case "ShippedDate":
ord.ShippedDate = $(this).find("#Data").val();
break;
}
Because I've already added a reference to my Web Service to the ScriptManager on my site's Master Page, I can just call my new UpdateCustomerOrders method from my client-side code:
NWCusts.UpdateCustomerOrders(ordList, OrdersUpdated, GenericFailure);
I still need to handle inserts and deletes, but you'll have to come back next week for those.

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/.

comments powered by Disqus

Featured

  • VS Code Now Has Apple Silicon Builds for Native Mac Development

    Goodbye Rosetta, hello M1. Visual Studio Code has been updated with new builds that let it run natively on machines with Apple Silicon (M1), the company's own ARM64 chips.

  • Visual Studio 2019 for Mac v8.9 Ships with .NET 6 Preview 1 Support

    During its Ignite 2021 online event for IT pros and developers this week, Microsoft shipped Visual Studio 2019 for Mac v8.9, arriving with out-of-the-box support for .NET 6 Preview 1, which the company also released recently.

  • Analyst: TypeScript Now Firmly in Top 10 Echelon (Ruby, Not So Much)

    RedMonk analyst Stephen O'Grady believes TypeScript has achieved the rare feat of firmly ensconcing itself into the top 10 echelon of his ranking, now questioning how high it might go.

  • Black White Wave IMage

    Neural Regression Using PyTorch: Training

    The goal of a regression problem is to predict a single numeric value, for example, predicting the annual revenue of a new restaurant based on variables such as menu prices, number of tables, location and so on.

Upcoming Events