Practical ASP.NET

Inserting with jQuery

Peter continues to extend his client-side case study by using jTemplate to extend a table to support inserts -- and then sending the user's data to the server to update the database.

This series started with the Visual Studio Magazine article Integrating jQuery, Web Services, AJAX and ASP.NET (December, pg. 24), which integrated the ASP.NET ScriptManager and jQuery to implement client-side CRUD processing. Subsequently, over three columns (Defining Templates with jTemplate, Updating From the Client and Deleting with jQuery and Web Services), I've extended the article's case study to do everything but insert new rows of orders -- which is what this column is all about.

Structuring the HTML and templates
To insert a new row into the page's HTML table, I need to generate a row using my jTemplate template. My first step is to restructure my existing template, which currently generates the whole table, to generate only a single tablerow:

{#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›
...more cells for other Order data...
‹/tr›
{#/for}
The rest of my original table template now goes into my page where I use the table's style attribute to make the table invisible. I also assign an id to the table's tbody tag so that I can target it from jQuery:
‹table id="OrdersTable" style="display:none;"›
‹thead›
‹tr›
‹td width="20%"›Delete‹/td›
‹td›Order Id‹/td›
‹td›Shipped Date‹/td›
‹/tr›
‹/thead›
‹tbody id="OrdersTableExisting"›
‹/tbody›
‹/table›
With jQuery, displaying the table after loading it with Order data requires just this:
$("#OrdersTable").show();         
I then added a div element to my page to act as a staging area when generating my new table row:
‹div style="display:none;" id="OrdersTableInsert"›‹/div›
Processing the template
I now added a new HTML button to my page and had it call the following function to generate a row and add it to the table. This code picks up the file holding my template and associates it with my staging area element. I then create an instance of my client-side object and set its properties to any defaults I have for a new order. I add that object to an array, pass it to the jTemplate processTemplate command, generate a row into my staging area, and append that new row to my table:
function DoAddRow() 
{
$("#OrdersTableInsert").setTemplateURL("Templates/OrdersTable.htm");
var ordIList = new Array;
var ord = new NorthwindOrder();
ord.OrderId = "‹..›";
ordIList.push(ord);
$("#OrdersTableInsert").processTemplate(ordIList);
$("#OrdersTableExisting").
append($("#OrdersTableInsert")[0].innerHTML);
}
Processing Inserts
Eventually, the user will click a button and I'll process any inserted rows. First, I set up a variable to hold NorthwindOrder objects, an array to hold any objects I create, and retrieve the id of the Customer the user selected in the drop-down list on the page:
var ord;
var ordIList = new Array();
var CustId = $('#ctl00_MainPlaceHolder_ListBox1')[0].value;
I'll use my default OrderId ("‹..›") to find any inserted rows, but I don't want to retrieve the tablecells containing "‹..›" -- I want the tablerow with those cells. This jQuery finds all the tablerow elements in my OrdersTable and then filters that list down to just the rows with "‹..›" inside:
$("#OrdersTable tr").filter(":contains('‹..›')").each(function() {
In the function that jQuery calls for each element retrieved, I first create an instance of my NorthwindOrder object and then process every cell in the row (again, using jQuery). For each row, I retrieve the input element inside the cell (all of which have an id of "Data") and, based on the cell's id, set the appropriate property on the Order object. Finally, I set the CustId property using the value from the drop down list and add the object to my array:
ord = new NorthwindOrder();
$(this).find("td").each(function()
{
switch (this.id) {
case "ShippedDate":
ord.ShippedDate = $(this).find("#Data").val();
break;
...more properties set...
}
ord.CustId = CustId;
ordIList.push(ord);
After processing all the rows, I check to see if there are any objects in my array and, if there are, pass the array to a Web Service to do the database updates:
if (ordIList.length › 0)
{
NWCusts.InsertCustomerOrders(ordIList, OrdersInserted,
GenericFailure);
}
Inserting the List of Orders on the Server
In my Web service, I'm using Entity Framework and LINQ to do my database changes. In addition to creating the EF object that represents my Orders table, I also have to retrieve the related Customer object so I can add the Order to that Customer:
Dim entsNW As New northwndModel.northwndEntities
Dim NWOrder As northwndModel.Orders

For Each ord As NorthwindOrder In Orders
NWOrder = New northwndModel.Orders()
NWOrder.ShippedDate = ord.ShippedDate
...set other properties...
cust.Orders.Add(NWOrder)
Dim cust = (From custmr In entsNW.Customers _
Where custmr.CustomerID = ord.CustId _
Select custmr).First
entsNW.AddToOrders(NWOrder)
Next
entsNW.SaveChanges()
After one article and four columns, I've got a page with full CRUD functionality for both single and multiple records, combining AJAX for ASP.NET, WCF, jQuery, and jTemplate, Entity Framework and LINQ. The challenge, now, is for Visual Studio 2010 and .NET 4 to integrate these disparate technologies into a cohesive package for developers.

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