NovoGeek.com - Krishna's weblog

A technical blog on ASP.NET, AJAX, jQuery and .NET technologies

Developers who have tried jQuery UI Tabs plugin might have tried AJAX mode, which is really useful in meeting several requirements. The documentation clearly explains how to start using AJAX tabs.  However, there would be few hiccups if the plugin is not clearly understood. Below are some of them which I have faced recently:

Problem 1: In AJAX mode, sometimes, tabs do not load on a single click. You need to select a tab twice (double click) to open a tab.

Reason: Unfortunately, this is due to a bug in the plugin and happens when your AJAX calls fail.  Error handling is not done properly in jQuery tabs plugin as of the current version(1.7.2). More about this bug here. It can be resolved by applying the patch as described in the ticket. Hopefully, it would be fixed in the next release.

Problem 2: The “spinner“ option does not work by default (Spinner lets you provide a default “loading…” message in the tab, during tab load).

Resolution: To show spinner, the content of anchor tags inside “<li>” must be enclosed in “<span>” tags. More info here…

Problem 3: Displaying custom “loading” message in the tab body (and NOT in the tab).

Resolution: Overwrite the default spinner and make use of “select”, “show” functions. More Info here…
(Note: When tabs are cached, “load” will not get triggered for the second time. So use “show” instead of “load” while caching).

Problem 4: Remove “flickering” of tabs on page load.

Resolution: As you might have expected, simply hide the tabs container using CSS (display:none) and show it using jQuery after tabs are built as below:

$('#TabsDiv').tabs({.....}).css('display','block');

Problem 5: Tab panel/body is not removed from the DOM when a tab is closed.

Resolution: This is indeed a tricky problem. This happens when tabs are disabled! Wondering what is the relation? It’s simple. When a tab is disabled, the “<li>” element, which makes the tab header, will be displayed in a dull style. But the corresponding “div”, which makes the tab panel/body is not rendered.

So, there would be a difference in indexing between tab header & body and thus the tab body is not deleted. Hence, do not disable tabs when you want to remove them based on index! (You may debug the first two lines of “remove:” function in the plugin to test this).

Problem 6: Prevent “auto selection” of adjacent tab, when a tab is closed.

Resolution: The Tabs plugin mimics “Firefox” tabs with respect to auto selection of a tab, when another tab is closed. However, sometimes, you might need to select a farther tab on closing of a particular tab. This cannot be achieved by overriding the “remove” callback. So simply comment the below lines in “remove” function and write your code to select the desired tab in your close button click event.

// If selected tab was removed focus tab to the right or 
        // in case the last tab was removed the tab to the left. 
        if ($li.hasClass('ui-tabs-selected') && this.anchors.length > 1) { 
            this.select(index + (index + 1 < this.anchors.length ? 1 : -1)); 
        }

Note: I’m using jQuery tabs inside UI.Layout plugin in my project. At first, I thought that the layout plugin is messing up my code and causing these issues. After straining for 3 days, I could figure out the above solutions. So folks using the UI.Layout plugin need not worry about Tabs plugin integration. Their combination works perfectly.

Hope this article saves the time of many enthusiasts who might face similar problems. Happy coding :)


If you are an ASP.NET web developer using jQuery for AJAX, you would have probably got used to passing parameters through DTO (Data Transfer Objects) as suggested by Dave in Encosia.com. This is a clean and simple approach for passing parameters from client to server.

Unfortunately, many jQuery plugins are not coded this way and need to be tweaked. Same is the case with jqGrid, which is an excellent jQuery grid plugin. So below are the simple tweaks to be made for jqGrid to support DTO's.

At a basic level, these tweaks should be  done in the "grid.base.js" file. If you are using plugins for inline edit or any other feature which makes AJAX calls, the same changes have to be made there also.

There are things which need to be changed in all AJAX calls made by the plugin:

1. Building a Data Transfer Object(DTO).

2. Setting the content-type to "application/json".

3. Convert the input object into  JSON string.

4. Filtering .NET's "d" parameter in the AJAX success function.

1. Building a DTO: In "grid.base.js", search for the code "populate = function() { ", which is the definition of populate function (This is in line 577). In this function, add the code in bold, above the switch statement (which is in line 588).

var jsObj = { 'obj': ts.p.postData }; //Building a DTO
switch (dt) {
                    case "json":
                    case "xml":
                    case "script":

2. Setting the content-type to "application/json":

  In line 593, add the JSON content type as a parameter to $.ajax function.

3. Convert the input object into  JSON string:

 In the same lin(593), replace the data parameter with JSON stringified DTO.

The code change for (2) and (3) will now be:

  Old Code:  $.ajax({url:ts.p.url,type:ts.p.mtype,dataType: dt ,data: ts.p.postData, 

  Tweaked code: $.ajax({ url: ts.p.url, type: ts.p.mtype, dataType: dt, contentType: 'application/json; charset=utf-8', data: JSON.stringify(jsObj),

 4. Filtering .NET's "d" parameter in the AJAX success function:

Finally, filter .NET's "d" parameter in the line 596 like below:

  Old code:   if(dt === "json" || dt === "script") addJSONData($.jgrid.parse(req.responseText),ts.grid.bDiv,rcnt);

  Tweaked code:  if (dt === "json" || dt === "script") addJSONData($.jgrid.parse(req.responseText).d, ts.grid.bDiv, rcnt);

That's it! The grid should now be able to handle JSON objects as input parameters and should bind JSON data successfully. Note that I have done these tweaks in jqGrid 3.5. The same concept applies to lower versions of jqGrid too. However, the line number and variables used in AJAX calls differ.

Hope this article would save the time of many enthusiasts, who want to use jqGrid in their ASP.NET projects. I shall come up with a detailed post on other common problems shortly.


In .NET 3.5, when a Web service class is decorated with “ScriptService” attribute, the web service returns data in JSON format [MSDN]. I have demonstrated this with a simple example in the article, Passing JSON objects in .NET 3.5.

Let us consider that our “person” class has several properties, of which only few are useful on the client side for data binding. We can filter this object in two ways:

1. On the server side:- Create a dictionary object [System.Collections.Generic.Dictionary(Of TKey, TValue)], add the desired properties to dictionary object and return it.

2. On the client side:- In cases where a quick filter has to be done without touching server side code, we can use jQuery’s each function to create a custom JSON object.

Suppose you want to filter only “country” and “code” out of the below JSON data,

var players = 
[{ "country": "India", "code": "Ind", "name": "Sachin" },
{ "country": "Sri Lanka", "code": "SL", "name": "Murali" },
{ "country": "Australia", "code": "Aus", "name": "Shane" },
{ "country": "West Indies", "code": "WI", "name": "Lara"}];

you can simply write the below jQuery code:

var newObject = {}; //Creating a new object
$.each(players, function() { //Looping through our players array using jQuery's each function
    newObject[this.country] = this.code; //Creating our custom "name/value" pair
});

So, our newObject will contain new data(having only “country” and “code”). If you want to access country code, you can simply say “newObject.India”, which gives “Ind”.

This tip is particularly useful in cases like filling dropdown lists with JSON data. By default, the server’s JSON data contains several properties which are not required. In such cases, this client side filter comes as a handy tip :)


I was trying to use jqGrid, an excellent jQuery based grid, for building a zero postback page. It's configuration is very simple, similar to flexigrid, but has many additional features like inline editing, subgrids etc.

What jqGrid expects is a JSON response having few objects and arrays, which are mapped to columns in the grid inside the grid.base.js file, like this.

Though the grid's AJAX call is successful, data is not being bound to thegrid. The reason is, .NET 3.5 returns JSON object which is prefixed with a "d" parameter like this.

So, to map the JSON data to the grid, we have to manually parse the AJAX response and separate the "d" parameter in AJAX success callback. This applies not only to jqGrid, but also to all jQuery plugins which expect JSON response.

I was about to write more on why .Net 3.5 prefixes "d" to JSON response, how it enhances security and how to parse it easily., but incidentally, Dave ward explained the concept excellently in his latest article: http://encosia.com/2009/06/29/never-worry-about-asp-net-ajaxs-d-again

So no more worrying about .Net's "d" again :)


In my previous post, I have explained how to pass complex types using jQuery and JayRock in .NET 2.0 framework. I was digging a bit into Dave’s example (using complex types to make calling services less complex) in .NET 3.5 framework, to find how easier JSON serilaization/deserialization can be made.

When a Web service class is decorated with “ScriptService” attribute, which is in the System.Web.Script.Services namespace in .NET 3.5, the web service returns data in JSON format [MSDN]. Whether the returned value is a string or an object, it will be in JSON format. So no need of writing chunks of code for serializing objects explicitly.

Therefore, all that we need to do is to simply decorate our web service class with “ScriptService” attribute and  return an object from the server. So, to create a JSON object like this:

{"d":{"FirstName":"Krishna","LastName":"Chaitanya","City":"Hyd","State"
:"Andhra","Country":"India"}}

We can simply return a person object like this:

<WebMethod()> _
    Public Function fnFetchDetailsClass() As Person
        Dim objPerson As New Person
        Try
            objPerson.FirstName = "Krishna"
            objPerson.LastName = "Chaitanya"
            objPerson.City = "Hyd"
            objPerson.State = "Andhra"
            objPerson.Country = "India"
        Catch ex As Exception
 
        End Try
        Return objPerson
    End Function

In some situations (like in client side templating), we might need to create custom, complex JSON objects on the fly. In such situations, we can make use of .NET’s “ListDictionary” and “ArrayList” classes.

The above example can be re-written using ListDictionary as:

<WebMethod()> _
Public Function fnFetchDetails() As ListDictionary
    Dim jsonObj As New ListDictionary
    Try
        jsonObj.Item("fname") = "Krishna"
        jsonObj.Item("lname") = "Chaitanya"
        jsonObj.Item("city") = "Hyd"
        jsonObj.Item("state") = "Andhra"
        jsonObj.Item("country") = "India"
        Return jsonObj
    Catch ex As Exception
        jsonObj.Item("Error") = "Error at server"
        Return jsonObj
    End Try
End Function

Thus, using JSON is made easier in .NET 3.5.

Here is a simple demo which makes things clear. (I have used jQuery for making AJAX calls.)

(Note: ListDictionary stores values in Name/Value pairs, which is useful in building JSON Object. Similarly, an ArrayList can be used to build JSON Arrays. Therefore, these two can be used instead of JsonObject and JsonArray classes of Jayrock in my post Converting ASP.NET DataTable to JSON using JayRock.)


  • Share/Save/Bookmark
  • Entries (RSS)
  • Comments (RSS)

About

ProfilePic Hi, My name is Krishna Chaitanya and I'm a web developer from Hyderabad, India.

This is my online abode where I write about various technical topics, my little experiments related to web development in ASP.NET, jQuery etc. More...


Friends


Archive