Skip to content

jQuery-Ui Tabs and Asp.net MVC

March 17, 2009

Clay made a comment on my previous post and asked how I would use asp.net mvc with jQuery-UI’s tabs. I have slapped together an example project that shows how you could implement the tabs in an asp.net mvc web site. I created an ajax and a regular tab example.

Tab Example jQueryUi

Tab Example jQueryUi

Basically I use a partial view for each tab. This partial view is then also used for the ajax response.

<div id="tabs">
<ul>
	<li><a href="#tabs-1">Text 1</a></li>
	<li><a href="#tabs-2">Text 2</a></li>
	<li><a href="#tabs-3">Text 3</a></li>
</ul>
<div id="tabs-1">
            < % Html.RenderPartial("_tab1", Model);  %></div>
<div id="tabs-2">
	        < % Html.RenderPartial("_tab2", Model);  %></div>
<div id="tabs-3">
	        < % Html.RenderPartial("_tab3", Model);  %></div>
</div>

There is no database access in the example project, I sort of simulated a database by using a service model that provides the viewmodel that holds the texts that are displayed in the three tabs.

Regarding the ajax controller method, it would of course be better to not get the entire viewmodel in a real world situation and then pass that on to the view, but since this is a brief demo I thought I could get away with this in this example ;).


        public ActionResult getAjaxTab(int id)
        {
            string viewName = string.Empty;

            TabExample.Services.tabTextService serv = new TabExample.Services.tabTextService();
            tabViewModel myModel = serv.getTabViewModel();

            switch (id)
            {
                case 1:
                    viewName = "_tab1";
                    break;
                case 2:
                    viewName = "_tab2";
                    break;
                case 3:
                    viewName = "_tab3";
                    break;
                default:
                    viewName = "_error";
                    break;
            }

            System.Threading.Thread.Sleep(1000);   

            return PartialView(viewName, myModel);
        }

I am using this js function to update the tabs.


        function getContentTab(index) {
            var url='< %= Url.Content("~/Home/getAjaxTab") %>/' + index;
            var targetDiv = "#tabs-" + index;
            var ajaxLoading = "<img id='ajax-loader' src='<%= Url.Content("~/Content") %/>/ajax-loader.gif' align='left' height='28' width='28'>";

            $(targetDiv).html("
" + ajaxLoading + " Loading...
"); 

            $.get(url,null, function(result) {
                $(targetDiv).html(result);
            });
        }

There is a select event on the tabs that you can hook into as well, I just find it easier to just use the onclick event of the tab div's.

Hope this is some help to anybody out there, it was fun to create this small project. If anyone has any suggestions, or questions let me know in the comments !

Download TabExample Project Link

About these ads
54 Comments
  1. March 19, 2009 6:03 pm

    Nice one though, downloading sample project right now. I actually wanted to use JQuery Ui tabs in ASP.NET MVC in my current project. Now i don’t have to dig into the problems. I can watch an learn from your code.

  2. March 19, 2009 6:25 pm

    Thanks ! It was created with rc2, but should work with the new 1.0 as well !

  3. KBase permalink
    March 26, 2009 1:50 pm

    Tab Text Example- not getting data from server, only load first time.
    Ajax Tab Example – getting data from the server

    You are comparing performance for each one. but it is fake

    If you claim Tab Text Example takes data from server every time then drop me a message.

    • March 26, 2009 2:10 pm

      > Tab Text Example- not getting data from server, only load first time.

      The data in this example is indeed loaded when you load the controller / page holding the tabs.

      > Ajax Tab Example – getting data from the server

      Indeed, it does an ajax request to get the content for the tab you click on.

      > You are comparing performance for each one. but it is fake

      I am not comparing anything, just showing two different ways to do things.

  4. April 17, 2009 2:21 am

    Nice job on your implementation. I want to simply use the tabs to navigate to the controllers to pull each view from a MasterPage, so essentially only use the tabs as navigators without using the inner div tags but haven’t found a nice way to do this. I thought either through jQuery or Json I could call the controllers. Any suggestions?

    • April 17, 2009 8:55 am

      You could either use the 2nd method (the ajax one), but that means that you depend on javascript to load your pages. So if someone comes along that doesn’t use javascript he can’t load the site.

      You might me better off using a jquery menu plugin. And there are a lot of those out there ;).

    • April 17, 2009 5:17 pm

      Thank you for the follow-up I will take a look for an appropriate jQuery menu plugin.

      Cheers!

  5. April 18, 2009 12:30 pm

    Maybe this is a good one. Looks pretty nice:
    http://pupunzi.wordpress.com/2009/01/18/mbmenu/

  6. Ricky permalink
    April 21, 2009 9:17 pm

    In the Ajax Tab Example, when the page loads it is set to use the first content tab:

    $(document).ready(function() {
    $(“#tabs”).tabs();
    getContentTab (1);
    });

    I wanted to see if the page would load the second tab by updating it to use:

    getContentTab (2);

    Why does the document load the first tab but not second? What could I do to accomplish this?

    Thanks again for sharing!

    • April 22, 2009 7:29 am

      You have to activate the 2nd tab then load the content. Something like this:

                  $("#tabs").tabs('option', 'selected', 1);
                  getContentTab (2);
      

      The 1 in the first line is because it's a zero based index.

      Hope this helps !

    • Ricky permalink
      April 22, 2009 4:26 pm

      I ended up using:

      var $tabs = $(‘#tabs’).tabs();
      var selected = $tabs.tabs(‘option’, ‘selected’);
      var contentTab = $tabs.tabs(‘option’, ‘selected’, 1);

      getContentTab(2);

      Thanks again for your help!

  7. April 22, 2009 7:32 pm

    Ok that looks good too. Glad to be of service ;).

  8. Clay permalink
    July 9, 2009 6:43 pm

    A friend just sent me a link to this…and I thought hey that’s me!
    Thanks for the post!
    Nice example.

  9. colforbin permalink
    September 1, 2009 8:13 pm

    I am not sure exactly what you mean by this… I am new to MVC. Could you clarify and maybe lead me in the direction of what I should actually do for best results?

    Thanks!

    “Regarding the ajax controller method, it would of course be better to not get the entire viewmodel in a real world situation and then pass that on to the view, but since this is a brief demo I thought I could get away with this in this example”

    • September 2, 2009 8:19 am

      What you usually do is make a partial view strongly typed and render it like this Html.RenderPartial(Viewdata.Item); Instead of passing down the whole viewdata to the partial !

      Hope this helps :).

    • colforbin permalink
      September 2, 2009 3:10 pm

      So I would need to create a class for each tab partial view so you are passing a strongly typed into the RenderPartial()…. Then you just have to change the Inherits property for the partial view to use the newly created class….

      Is that correct ?

  10. September 2, 2009 3:21 pm

    Yes you could do it like that. Or do it just like the example if that´s more convenient :).

    • colforbin permalink
      September 2, 2009 3:34 pm

      What in your opinion is the best real world approach ?

    • Jacson permalink
      March 5, 2010 7:09 pm

      Yes you could do it like that. Or do it just like the example if that´s more convenien

  11. Paul Wallace permalink
    October 8, 2009 9:20 am

    Thanks for the example code, very helpful. I’ve run into a problem using accordions within tabs, the initially inactive accordions do not render there content correctly when their tab is selected. Reading around I see the reason for this is that the inactive tabs have display:none initially so the height of the divs within the accordion do not get calculated correctly. None of the suggested solutions work for me.
    Wondering if you have had to overcome this and have a work around?
    See code below for example of the problem:

    $(document).ready(function(){
    $(‘#tabs’).tabs();
    $(“#accordion1″).accordion();
    $(“#accordion2″).accordion();
    });

    Tab 1
    Tab 2

    Section 1

    Mauris mauris ante, blandit et, ultrices a, suscipit eget, quam. Integer
    ut neque. Vivamus nisi metus, molestie vel, gravida in, condimentum sit
    amet, nunc. Nam a nibh. Donec suscipit eros. Nam mi. Proin viverra leo ut
    odio. Curabitur malesuada. Vestibulum a velit eu ante scelerisque vulputate.

    Section 2

    Sed non urna. Donec et ante. Phasellus eu ligula. Vestibulum sit amet
    purus. Vivamus hendrerit, dolor at aliquet laoreet, mauris turpis porttitor
    velit, faucibus interdum tellus libero ac justo. Vivamus non quam. In
    suscipit faucibus urna.

    Section 3

    Nam enim risus, molestie et, porta ac, aliquam ac, risus. Quisque lobortis.
    Phasellus pellentesque purus in massa. Aenean in pede. Phasellus ac libero
    ac tellus pellentesque semper. Sed ac felis. Sed commodo, magna quis
    lacinia ornare, quam ante aliquam nisi, eu iaculis leo purus venenatis dui.

    List item one
    List item two
    List item three

    Section 4

    Cras dictum. Pellentesque habitant morbi tristique senectus et netus
    et malesuada fames ac turpis egestas. Vestibulum ante ipsum primis in
    faucibus orci luctus et ultrices posuere cubilia Curae; Aenean lacinia
    mauris vel est.

    Suspendisse eu nisl. Nullam ut libero. Integer dignissim consequat lectus.
    Class aptent taciti sociosqu ad litora torquent per conubia nostra, per
    inceptos himenaeos.

    Section 1

    Mauris mauris ante, blandit et, ultrices a, suscipit eget, quam. Integer
    ut neque. Vivamus nisi metus, molestie vel, gravida in, condimentum sit
    amet, nunc. Nam a nibh. Donec suscipit eros. Nam mi. Proin viverra leo ut
    odio. Curabitur malesuada. Vestibulum a velit eu ante scelerisque vulputate.

    Section 2

    Sed non urna. Donec et ante. Phasellus eu ligula. Vestibulum sit amet
    purus. Vivamus hendrerit, dolor at aliquet laoreet, mauris turpis porttitor
    velit, faucibus interdum tellus libero ac justo. Vivamus non quam. In
    suscipit faucibus urna.

    Section 3

    Nam enim risus, molestie et, porta ac, aliquam ac, risus. Quisque lobortis.
    Phasellus pellentesque purus in massa. Aenean in pede. Phasellus ac libero
    ac tellus pellentesque semper. Sed ac felis. Sed commodo, magna quis
    lacinia ornare, quam ante aliquam nisi, eu iaculis leo purus venenatis dui.

    List item one
    List item two
    List item three

    Section 4

    Cras dictum. Pellentesque habitant morbi tristique senectus et netus
    et malesuada fames ac turpis egestas. Vestibulum ante ipsum primis in
    faucibus orci luctus et ultrices posuere cubilia Curae; Aenean lacinia
    mauris vel est.

    Suspendisse eu nisl. Nullam ut libero. Integer dignissim consequat lectus.
    Class aptent taciti sociosqu ad litora torquent per conubia nostra, per
    inceptos himenaeos.

    • October 30, 2009 5:50 pm

      Oh sounds complicated. Has this bug been fixed yet ? Otherwise you’d need to work around it !

    • Paul Wallace permalink
      October 30, 2009 5:58 pm

      Solution is to load the accordians first:

      $(document).ready(function(){
      $(“#accordion1″).accordion();
      $(“#accordion2″).accordion();
      $(‘#tabs’).tabs();
      });

  12. Frank Footer permalink
    October 30, 2009 5:40 pm

    So with this example, how would you point to an ascx file in a different view folder or is that possible?

  13. October 30, 2009 5:49 pm

    You’d probably have to put the ascx in the shared folder ?

  14. Frank Footer permalink
    October 30, 2009 6:15 pm

    Well, this is how I did it… looks like each controller would need getAjaxTab(int id) or would need to inherit from a parent that has that method in it…

    So basically, adding a “view” argument to the getContentTab javascript function…

    $(document).ready(function() {
    $(“#tabs”).tabs();
    getContentTab (‘gumby’,1);
    });

    function getContentTab(view,index) {
    if (view == “” || view == null){
    view = “Home”;
    }
    var url=’/’ + index;
    var targetDiv = “#tabs-” + index;
    var ajaxLoading = “<img id='ajax-loader' src='/ajax-loader.gif’ align=’left’ height=’28′ width=’28′>”;

    $(targetDiv).html(“” + ajaxLoading + ” Loading…”);

    $.get(url,null, function(result) {
    $(targetDiv).html(result);
    });
    }

    function call:
    Text 1

  15. Frank Footer permalink
    October 30, 2009 6:17 pm

    crimony!… url is like this:

    var url=’/’ + index;

  16. Frank Footer permalink
    October 30, 2009 6:20 pm

    well, I see why you did screen shots now :-)

    var url='/' + index;

  17. November 11, 2009 10:10 pm

    Hi

    I’ve inserted all you javascripts and Style to my project, and did set all your adjustment exactly but the style of tabs does not work for me.

  18. Aditya Marla permalink
    November 26, 2009 11:05 am

    Really cool demonstration… Thanks for sharing this.

  19. Drew Millen permalink
    December 28, 2009 8:56 pm

    So, your solution was exactly what I was looking for, thanks! There is one thing I’m still trying to figure out; however.

    I’m using the AJAX example you’ve posted so when I click on a tab I call a controller action and generate a partial view in a div on the page. I’d like to allow my users to use the browser back/forward buttons and bookmark pages. Have you any ideas on how to implement this solution while preserving back/forward behavior of the browser?

    I’ve taken a look at Ben Alman’s jQuery BBQ (http://benalman.com/code/projects/jquery-bbq/examples/fragment-jquery-ui-tabs/#some_tabs=0); but it doesn’t assume you are using AJAX.

    Thanks in advance for any help!

  20. Pavan permalink
    February 12, 2010 4:20 am

    Hi,
    I have a different problem. I have an accordion control and each div (not the header but the content) has a Tab control and i am trying to load the accordion using the Ajax.

    First time, when add some content to the accordion, the tab control in that content loads fine. but, for everyother subsequent addition of content to the accordion, the tab controls dont load or should i say that they dont have a tab css set and hence they dont act like tabs. its just the content sitting out there.

    is it ok to have multiple jquery tab controls in one single page?

    is there anyway i can get some help…

    thanks a lot in advance,
    Pavan

    • February 12, 2010 8:36 pm

      I havent tried nesting various of those controls yet. Maybe you can ask over at stackoverflow.com ? I am sure some smart people will have an answer :).

  21. Arnold permalink
    April 7, 2010 1:53 am

    Hi Eric,

    I’ve been trying to implement your code into an MVC 2 application. I’m getting the error:

    The server block is not well formed on the following line. Note that my gif is in an Images folder off Content.

    var ajaxLoading = “<img id='ajax-loader' src='/ajax-loader.gif’ align=’left’ height=’28′ width=’28′>”;

    I have tried to rewrite this line, but without success. Do you (or someone else) know how to rewrite the line so tht .Net does not complain?

    Thanks!

    Arnold

    I’m using jQuery-1.4.2

  22. Arnold permalink
    April 7, 2010 1:56 am

    Hi Again,

    I t looks like the line got cropped when I copied when I pasted it in. Here it is again in bits:

    var ajaxLoading = “<img id='ajax-loader'
    src='
    /ajax-loader.gif’ align=’left’ height=’28′ width=’28′>”;

    Thanks,

    Arnold

  23. Arnold permalink
    April 7, 2010 1:59 am

    I’ll try one more time. This time I pasted into Notepad, first.

    var ajaxLoading = “<img id='ajax-loader'
    src='
    /ajax-loader.gif’ align=’left’ height=’28′ width=’28′>”;

    Fingers crossed.

    If we don’t see the entire line, just know that it’s the one beginning with:

    var ajaxLoading

    Arnold

    • April 7, 2010 9:10 am

      The way I do that these days is using CSS. So you append a class with display: none if you do not want to show the gif, and remove it if you want to. Or make a span of the give and do hide and show(). Very easy with jQuery !

      Hope this helps !

  24. Arnold permalink
    April 7, 2010 5:47 pm

    Hi Eric,

    Thanks for the tip! I’m new at jQuery and ASP.NET MVC, so I’m picking up whatever I can. I got your example working! Well..almost…It all works except for the fact that the jQuery tabs do not appear. My tabs page is a duplicate of yours. I summon the page in the browser url, something like:

    http://localhost:60768/Media/TabAjaxExample/1

    Debugging, I see that execution proceeds into the Media Contoller/TabAjaxExample Action. The correct view is populated with the correct model data.

    However, the page displays the correct data without tabs. It’s as though the tabs are not recognized as such. I’ve poured through the code comparing your implementation with mine, but I don’t see the critical difference. Do you have an idea what might be happening?

    Thanks, Arnold

    • April 7, 2010 5:53 pm

      It could be that you forgot to hook up the tabs in javascript. Dont forget this

      $(document).ready(function() {
      $(“#tabs”).tabs();
      });

  25. Arnold permalink
    April 7, 2010 7:07 pm

    Hi Eric,

    I see what is happening, now, but I don’t know why.

    The tabs page (TabAjaxExample.aspx) uses Site.Master, so I would expect its display to be accompanied by the master page code, with header and logo, etc.

    However, what I see in View Source is the partial view created in _tab1.ascx. That partial view should have been injected into the tab div.

    Thanks for any insight,

    Arnold

  26. Arnold permalink
    April 7, 2010 7:11 pm

    Eric,

    I definitely got the tabs hooked up:

    $(document).ready(function() {
    $(“#tabs”).tabs();
    getContentTab (1);
    });

    And it does return the tab number to the controller, through the function getContentTab().

    -Arnold

  27. Arnold permalink
    April 7, 2010 9:15 pm

    Eric,

    I’m so new to this.

    I found out my problem. Now everything works perfectly!

    Thanks for your patience and the great example!

    Arnold

  28. Arnold permalink
    April 11, 2010 11:08 pm

    Hi Eric,

    I have yet another question.

    If I were to place a Submit button on a partial view loaded into a tab via the Ajax method you describe above, what would the code to post back changed data look like? I don’t suppose I could get away with something like this?

    var url=’/’ + index;

    Thanks,

    Arnold

  29. Arnold permalink
    April 11, 2010 11:15 pm

    Sorry, forgot about the gator tags which shall be hereafter referred to as gtl; and gtr;

    I meant something like this:

    var url=’gtl;= Url.Content(“~/Home/MyPostBack”) gtr;/’ + index;

    Thanks,

    Arnold

  30. NIck permalink
    April 14, 2010 9:34 am

    Erm… How can I get this to run in VS 2010? Im trying to convert it but it fails

    • April 14, 2010 9:55 am

      This blogpost was written over a year ago using mvc 1.0, so you’ll have to be a bit creative and try and get it to work. The underlying techniques should still be the same.

  31. April 15, 2010 3:07 am

    Useful information..thx Thank You for having us
    excellent information, thank you thanks for the inspiration!

  32. June 24, 2010 7:03 am

    Good one. Used it as starting point and got myself a jQuery UI book.
    Working it into an Asp.Net MVC 2 Sample you can view/download here: http://jquery.krokonoster.com/

  33. VINAYAK permalink
    January 17, 2011 11:51 am

    Hi,
    I want to do a Jquery POST and get a chart using renderControl (which will return HTML attributes) I have successfully done this on WEbforms, However the same with MVC give a empty image. The handler doesn’t perform the same in MVC2 3.5. I went near to 50 sites now.

    No solutions could resolve this.

    I can’t use base64encoding as IE6, 7 don’t support it.

    I have few data parameteres to be sent to server and in response get the Chart image along with some table data all this to be done using JQUERY. No postbacks to be used.

  34. VINAYAK permalink
    January 18, 2011 5:10 am

    Hi PLZ use this comment for reply,
    I want to do a Jquery POST and get a chart using renderControl (which will return HTML attributes) I have successfully done this on WEbforms, However the same with MVC give a empty image. The handler doesn’t perform the same in MVC2 3.5. I went near to 50 sites now.

    No solutions could resolve this.

    I can’t use base64encoding as IE6, 7 don’t support it.

    I have few data parameteres to be sent to server and in response get the Chart image along with some table data all this to be done using JQUERY. No postbacks to be used.

  35. Ken permalink
    March 11, 2011 5:12 am

    Hi,
    Is there a way in the “Tab Text Example” to dynamically determine which tab is selected? For example, I would like tab2 to be the one selected when I click on the Tab Text Example link.

    Thanks,
    Ken

  36. Ricardo permalink
    June 26, 2011 5:32 am

    Great article… I applied this article using TabStrip ASP MVC component from Telerik and the result was very good. Telerik have the “Load on Demand of Content”:

    http://demos.telerik.com/aspnet-mvc/tabstrip/ajaxloading

    But It was not working the way that I wanted and your article gave me what I needed to load on demand my content and showing the little image “Loading”.

    Thanksss

Trackbacks

  1. This Week in jQuery UI vol. 2 « jQuery UI Blog

Comments are closed.

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: