Wednesday, January 27, 2010

ASP.NET MVC links for jQuery tabs

To work fully, including the loading indicator when using AJAX tab loading, jQuery expects your tab set up to be something like:

<div id="tabs">
<ul>
<li><a href="/controller/action1"><span>Tab 1</span></a></li>
<li><a href="/controller/action2"><span>Tab 2</span></a></li>
<li><a href="/controller/action3"><span>Tab 3</span></a></li>
</ul>
</div>

Note that the standard HtmlHelper extension for a link has trouble producing the correct anchor tag. If you specify HTML in the link text, it will be encoded on output. This is decidedly not what you want.


After several project where I used jQuery to wrap the anchor text in a span on page load, I decided that it would be just as easy (perhaps easier) to simply add a new extension named TabLink to my existing collection of extensions and simply generate the anchors with the embedded span for tab links.



public static string TabLink( this HtmlHelper helper, string text, string action )
{
return TabLink( helper, text, action, null, null, null );
}

public static string TabLink( this HtmlHelper helper, string text, string action, string controller )
{
return TabLink( helper, text, action, controller, null, null );
}

public static string TabLink( this HtmlHelper helper, string text, string action, string controller, object htmlAttributes )
{
return TabLink( helper, text, action, controller, null, htmlAttributes );
}

public static string TabLink( this HtmlHelper helper, string text, string action, string controller, object routeValues, object htmlAttributes )
{
var urlHelper = new UrlHelper( helper.ViewContext.RequestContext );

var anchorBuilder = new TagBuilder( "a" );
anchorBuilder.Attributes.Add( "href", urlHelper.Action( action, controller, routeValues ) );
anchorBuilder.MergeAttributes( new ParameterDictionary( htmlAttributes ), true );

var spanBuilder = new TagBuilder( "span" );
spanBuilder.SetInnerText( text );

anchorBuilder.InnerHtml = spanBuilder.ToString( TagRenderMode.Normal );

return anchorBuilder.ToString( TagRenderMode.Normal );
}


Used as:


<div id="tabs">
<ul>
<li><%= Html.TabLink( "action1" ) %></li>
<li><%= Html.TabLink( "action2", "controller" ) %></li>
<li><%= Html.TabLink( "action3", "controller", new { id = "tab3" } %></li>
<li><%= Html.TabLink( "action4", "controller", new { page = 1 }, new { id = "tab4" } %></li>
</ul>
</div>


<script type="text/javascript">
$(function() {
$('#tabs').tabs();
});
</script>

4 comments :

  1. Do you have an example in which you use this method for loading Tabs?

    Thanks,

    asmithDeveloper

    ReplyDelete
  2. The project on which I used the code is an intranet app so it's not really possible to have you access it. The example at the bottom of the article is pretty close to what I use, though I think I'm only using the action/controller signature. I'll update it to include the jQuery code as well.

    ReplyDelete
  3. Thanks so much, Timothy!

    -Arnold

    ReplyDelete
  4. Timothy,

    Including the jQuery code would be great for a newbie like myself. I'm trying to build lazy-loading tabs. A click should pass the tab number to the Controller where it will be evaluated and the return a formatted View. Is this possible?

    Thanks,

    Arnold

    ReplyDelete

Comments are moderated.