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

  • Hands On: New VS Code Insiders Build Creates Web Page from Image in Seconds

    New Vision support with GitHub Copilot in the latest Visual Studio Code Insiders build takes a user-supplied mockup image and creates a web page from it in seconds, handling all the HTML and CSS.

  • Naive Bayes Regression Using C#

    Dr. James McCaffrey from Microsoft Research presents a complete end-to-end demonstration of the naive Bayes regression technique, where the goal is to predict a single numeric value. Compared to other machine learning regression techniques, naive Bayes regression is usually less accurate, but is simple, easy to implement and customize, works on both large and small datasets, is highly interpretable, and doesn't require tuning any hyperparameters.

  • VS Code Copilot Previews New GPT-4o AI Code Completion Model

    The 4o upgrade includes additional training on more than 275,000 high-quality public repositories in over 30 popular programming languages, said Microsoft-owned GitHub, which created the original "AI pair programmer" years ago.

  • Microsoft's Rust Embrace Continues with Azure SDK Beta

    "Rust's strong type system and ownership model help prevent common programming errors such as null pointer dereferencing and buffer overflows, leading to more secure and stable code."

  • Xcode IDE from Microsoft Archrival Apple Gets Copilot AI

    Just after expanding the reach of its Copilot AI coding assistant to the open-source Eclipse IDE, Microsoft showcased how it's going even further, providing details about a preview version for the Xcode IDE from archrival Apple.

Subscribe on YouTube

Upcoming Training Events