11 August 2009

Populating Table Data using jQuery

There was an enhancement on the backlog at The Office this month where we needed to show a table of up to four products from a list of up to ten alternatives.  The user would select the four desired products to compare from a checkbox list and the details of those four would be inserted immediately into the table.

There was a great deal of rumination over what constituted the best approach.  We’re running a .Net 2.0 web site, so should we go for an ASP.Net Table, an HTML table that is rendered on the server-side or some other variation thereof?  For reasons that escape me today, we didn’t seriously consider using jQuery and now that we’re almost into the UAT phase, I can’t shake the feeling that we missed the better approach.

So I’m going to have a look for myself.  I’m going to go through the process of building the feature using jQuery AJAX to retrieve data objects (in the form of XML) from the server and populating a pre-existing table based on the properties of those data objects.  My example will be a little more simplified than the tack we actually took, but the theory will still be the same.

First Things First

First, let’s set up an ASP.Net website.  I’m deliberately not using MVC here because I want this demo to be a reasonable reflection of what we might have implemented had we not taken the server-side controls route.

I’m going to go ahead and create a default page and code up an unordered list and a table.  I’m using a grid layout to make landscaping the page a little easier.  I’m quite attached to this approach, but really you could just as easily download a free template straight from any good open designs site.

You’ll notice a couple of things when you download the source for this post.  First is that this has been tested in current, standards-compliant browsers only.  That means IE8, folks.  If you’re using an earlier version, strangeness may happen.  The other key thing to note is that the table includes a <colgroup> element.  This is important because you can’t create these (or cols for that matter) using the .Net Table control and that is the whole crux of the problem: adhering to the design specification.

jQuery will allow us to still retrieve and display the data we want, but also gives us the freedom to take full control of our HTML and CSS.  Our <colgroup> element requires that a background image be set for the first column and that columns are zebra-striped.  While we could accomplish this in code by assigning a specific class to each cell, the overhead (to a small degree in performance and efficiency of code, but primarily in tidiness of mark-up and page size footprint) would be far more than was necessary.

Design ingredients

The Front End

As previously mentioned, we have two key design features on the page and one key element in the HTML.

The design features are our unordered list and our table.  These are pre-set on the page ready to be populated by our code shortly.  Their styles are all set on the front end through the assigned classes for each element and the CSS alongside.  No cosmetics were applied in code-behind.

The Script

We have three main activities happening here: setting up our Ajax calls, populating our list of available products and getting a user-selected product.

Ajax Setup

I don’t need to go into detail about this part since Dave Ward has already done it for me.  Thanks, Dave!

Populate Product List

The first step in getting our page interacting with the data behind is to provide a list of products that our user can select from.  For the purposes of this demonstration, we’re just going to use an unordered list.  You could use a checkbox list, radio buttons or – my personal favourite – you could use jQuery UI’s selectable feature (I would have for this demo, but don’t want to over-complicate things).

This task is accomplished with our GetProductsList function.  There’s not much to it either; just a call to our GetAllProducts Web Method on the server end.  I’ll talk more about that shortly.  Once I’ve populated the list, I set up the event listener for a click on any list item.  The click event will fire the GetSelectedProduct function.

Get Selected Product

When the user clicks on our now-populated list of available products, jQuery will call the GetProduct method and pass in the ProductID, found in the id property of our list items.  Once it receives a response, we call the PopulateTable function.

Render Table

The PopulateTable function is responsible for taking our data object (a product) and placing the information found in its various properties in the table (obviously).  Step one is to find the index of the first available empty column.  If our table doesn’t have a value in its header, it doesn’t have one in the corresponding body columns either.  However, if we’ve already selected this product, I want to remove it from the table instead.  We’ll find this by searching for the cell with the ID value we want and if it can’t be found, we’ll just take the first available empty cell.

if ($('#product-table').find('th[id=' + response.Id + ']').html() == null) {
var cell = $('#product-table thead th:not(:first):empty:first');
}
else {
var cell = $('#product-table').find('th[id=' + response.Id + ']');
}

The next step is to get the Index of the selected column – whether populated or not – and create a reference to the rows in the table body.  If my table is empty, I’m going to fill each cell in the column with a specific data object property.  If there’s already something there, I’m just going to clear out those cells.

The Back End

So that’s our basic front-end logic done.  There are no doubt plenty of embellishments you could add, given enough time.  Time to look at the server-side code.

As you might expect, there’s not much here.  There are two web methods on the default.aspx page code-behind: GetProduct and GetAllProducts.  These just pass the grunt work to our object and data classes and return whatever they’re given as a result.

The ProductRepository is the main engine room of the demo.  This class is tasked with retrieving all nodes from our XML file or a specific one depending on whether an ID is supplied or not.  The repository grabs its information and feeds that into one or more Product objects.  These objects are then returned back to the calling class.

The Colouring-in

The CSS for this demo is essentially the whole point of doing it in the first place.  I want to style the table presenting our data in a way that would not be possible without a considerable amount of smoke and mirrors on the server side.

Because we’re adding and removing content from our table columns arbitrarily, it doesn’t make sense to style the individual cells and rows each time.  If we were to take that approach, we’d need to re-style the table based on where cells were positioned in the table.  Rather, it makes more sense to define styles for an entire column of information at a time using the previously-mentioned <col /> element.

For example, you’ll see that the first column of the table has a background image that spans all the rows of the table.  This is the tbl-products-first class and would not be achievable through assigning cell-by-cell classes.  The zebra-striping of the other columns is again achieved using <col /> elements and – while possible with individual class assignment – is much cleaner as a consequence.

Finally, the border on the right cell of our table demonstrates that it is much simpler if we do want to style some columns individually.  If we had the entire table pre-rendered and were showing or hiding columns using script, we’d have to go back over our table each time and reapply this style.

Summing Up

So that’s our jQuery / table demo.  What it shows is that sometimes it is actually much less work to opt away from server-side controls.  Knowing and judging the most appropriate times for each approach is key for good UI and code maintainability.  You can download the source code for the demo or view a working version here.

Tags: , , , ,

3 Responses to “Populating Table Data using jQuery”

  1. Quinto says:

    Interesting how I landed on this page. I am trying to find a way to create a jquery table with products and pricing that adds up the total product cost, based on the items selected using a check box.
    say I have a list of items like product x = $ 2
    product y = $ 4
    product z =$ 3
    Now using a check box, if I select products y and z, I should get total cost of $7 displayed at the bottom…any help with that ? If nothing is checked then total should read $ 0

  2. Phil says:

    Fun. Let me write up a quick demo for you with an explanation of the code. Stay tuned. When do you need it?

  3. Phil says:

    Ok, I’ve thrown together a cheap and cheerful implementation for what you’re after. I’ll do a blog post explaining it later, but the page is found at http://demos.officeacuity.com/Demo/Products. The code is currently only embedded in the page, i.e. you need to View Source on the page to see how I’ve put it all together.

    Housekeeping and blog post in due course. Let me know if this helps you out.

Leave a Reply

Real Time Web Analytics