jQuery Form and jQuery UI Tabs: Two great tastes that taste great together
I spent last week holed up writing part 4 of Ajax Overhaul, my series of articles for IBM developerWorks. Aimed squarely at Ajax beginners, the series shows how to progressively enhance Web 1.0 sites with jQuery and Ajax. Each installment starts with the pre-Ajax version of an example e-commerce application and takes readers through the steps of retrofitting it to improve and modernize the user experience. The tagline for this installment is "Streamline multi-step processes with tabs and Ajax forms," a topic that allowed me to employ two of my favorite plug-ins for the jQuery open-source Ajax toolkit:
- jQuery Form, which gives jQuery several methods for serializing form data and submitting the results via Ajax.
- jQuery UI Tabs, which turns a series of divs and unordered lists into a tabbed interface.
I feel like I've run on and on about my enthusiasm for jQuery on this site, but I can't help it. One of the cool thing about its plugin ecosystem is the ease with which you can cross-pollinate a couple of plugins to create novel effects. In this case, I wanted to take a series of web forms - the checkout process for my example shopping site - and turn them into a single-page, tabbed interface in which each tab represented one step of the process. The biggest additional requirement was progressive enhancement; with JavaScript absent or disabled, the checkout process has to work like it did before I retrofitted it. All it took to accomplish these goals was a judicious mix of my two plugins.
jQuery UI Tabs allowed me to pull several individual form pages into a single HTML shell via Ajax. It also allowed me to control which tabs were selectable at any given time; that way, users could jump back in the process to re-submit one of the earlier forms but couldn't jump forward to fill out forms out of order. This was important because in my example application, input in the earlier forms can affect the output of subsequent forms. Jumping back allows you to change your input, but it forces you to repeat all the intermediate steps over which you skipped.
Luckily, jQuery UI Tabs allows you to enable and disable tabs with ease. You can disable them as a group in the options bundle you use to initialize the tab set. Then you can enable or disable individual tabs by calling the appropriate methods on them. In my example code, it made sense to disable all but the first tab by default. Then I provided a custom callback function that executes each time a new tab is selected, cycling through the list and disabling all but the previous tabs in the process. The resulting code, executed when the DOM is ready, looks like this:
var tabSet = $('ul.navTabs').eq(0).tabs( { /*apply a nice visual effect to tab activation*/ fx: { height: 'toggle', opacity: 'toggle' }, /*disable all but the first tab by default*/ disabled: [1,2,3,4] }).bind('select.ui-tabs', function(event, ui) { /* ensure that each time a new tab is activated all subsequent tabs are disabled. This will prevent users from jumping around in the process */ var currentTab = parseInt(ui.tab.id.substring(3)); var tabSetLength = 5;//hack; UI tabs doesn't know its own length for (var i = 0; i < tabSetLength; i++) { if (i > currentTab) { tabSet.tabs("disable", i); } }});
jQuery Form, meanwhile, provided the plumbing for the individual forms that I plugged into the tabs I'd just created. It allowed me to redirect the submission of each form so that it occurs via Ajax and the response gets rendered inside the next sequential tab. This all happens thanks to the power of the ajaxSubmit method that the plugin adds to the jQuery object. jQuery Form does offer a simple Ajax submittal method, ajaxForm, but the more versatile ajaxSubmit method provided the flexibility I needed. It let me pass in a target DOM node in which to render the response, override the action URL of the original form tag and define a custom callback function to enable and select the tab representing the next step in the process. The code for each individual form varies a bit, especially for steps in the process that include detours (such as logging in or applying a discount code). But here's a typical example:
//bind the form and provide a callback function$('#sform').submit(function() {
//submit the form via ajax $(this).ajaxSubmit({ target: '#billingDetails', url: 'checkout3-fragment.html', success: function() { var tabSet = $('ul.navTabs'); tabSet.tabs("enable", 2); tabSet.tabs("select", 2); } });
//don't actually submit the form normally return false; });
As always, it will take a few months for my draft to make it through the editing process and onto the developerWorks site. But you can take a peek at the above-quoted code in action over at Pathfinder Labs. FYI for anybody peeking under the hood: My example app is just a front-end mockup with no server-side code to support it.
If anyone's remotely interested, you can also monitor the Ajax Overhaul page on developerWorks to see when the actual installments get published.
Related Services: Ajax Rich Internet Applications, Custom Software Development









That’s a nice form setup you have going. I know its still in the design phase but I’d like to suggest incorporating the jQuery remoting plugin, so that the user’s back button isn’t broken. I hit it half-way through the form, and it brought me back to this page (and of course lost all of my information), when all I wanted to do was go back to the previous tab.
@kenman: I should have mentioned that! As with all my tutorials for IBM, I can only cover a few topics in the space allotted. I’m pitching additional topics to IBM and hope to do an additional piece on Ajax history management. I definitely plan to check out jQuery’s history management options, though any published piece will probably focus more on Really Simple History, the Ajax history plugin that I help maintain.
This is great! Thank you! You mention the following, “users could jump back in the process to re-submit one of the earlier forms but couldn’t jump forward to fill out forms out of order.” Is it possible to retain all the steps’ inputted data if, lets say, I’m on step 5 and skip back to step 1 (Step 1-4 would still be populated with what I inputted)?
@EdT: Because modern browsers only cache form values across a session for form fields that are part of the DOM before window.onload fires, form values caching is an issue with an Ajax application. In my demo, we only load each tab’s contents once; on subsequent visits to that tab, we just display the existing tab. But in the real world, you would probably reload each tab from the server each time you hit it, and you would use server-side processes to persist the data where possible (that is, where changes to your answers in an earlier step in the process don’t make that problemmatic – e.g. going back to the shipping step and unchecking the “use this as my billing address” boxs).
sry its a teest
[…] jQuery Form and jQuery UI Tabs: Two great tastes that taste great together […]
You may try a plugin called baby steps which does what you require but in an easier manner
Lets say I am on tab3 and i am reloading the page. In my case I am back on tab1. How to make sure tab is selected when the page is reloaded?