How To: Make Tab control panels load "on-demand"

Several people have asked about how to make the contents of their tabs load when the user first clicks them, thereby reducing initial page size.

I can think of several ways to do this with varying levels of complexity, but here's away you can do right now with minimal hacking.  We'll think about how to build this in.  But for now...

Basically we can do this with UpdatePanels. 

What we'll do is:

  1. Add an UpdatePanel inside each TabPanel
  2. Add a hidden button to trigger that update panel
  3. Add a Panel with Visible="false" that has the content we want to load inside of it (Visible false prevents it from rendering at all)
  4. Write some JavaScript to trigger that button.

Let's get started.  First, we just create an empty AJAX Enabled project and drop an AjaxControlToolkit TabContainer on the page.  Add some TabPanels:

<

act:TabContainer ID="tc1" runat="server" >

<act:TabPanel HeaderText="TabPanel0" runat="server" >

<ContentTemplate>

This is the inital tab.

</ContentTemplate>

</act:TabPanel>

<act:TabPanel HeaderText="TabPanel1" runat="server" >

<ContentTemplate>

We want to load this later.

</ContentTemplate>

</act:TabPanel>

</act:TabContainer>

Next, to each TabPanel, add an UpdatePanel, and inside that a Button and a Panel.  Note the OnClick handler on the Button and the naming of the button and the panel.  On the button, set it's style to "display:none;" so the browser hides it.

<act:TabPanel HeaderText="TabPanel1" runat="server">

<ContentTemplate>

<asp:UpdatePanel ID="up1" runat="server">

<ContentTemplate>

<asp:Button ID="TabButton1" runat="server " OnClick="TabButton_Click"  style ="display:none;"/ >

<asp:Panel ID="TabContent1" runat="server"Visible ="False" >

We want to load this later

</asp:Panel>

</ContentTemplate>

</asp:UpdatePanel>

</ContentTemplate>

</act:TabPanel>

Now on the server side, we add some code to handle the click.  Again, note how we use the naming. 

Protected Sub TabButton_Click(ByVal sender As Object, ByVal e As System.EventArgs)

' find the sibling with the name that starts with TabContainer

'

Dim containerId As String = "TabContent" & tc1.ActiveTabIndex

Dim panel As Panel = tc1.ActiveTab.FindControl(containerId)

If (Not panel Is Nothing) Then

panel.Visible =

True

End If

End Sub

Here, we just flip the Visible property to true.  You could, of course, do a databinding operation here or whatever.

Now we just wire it up.  We add some JavaScript to handle this hookup for us to the top of the page, and set the "OnClientActiveTabChanged" property on the TabContainer. 

<act:TabContainer ID="tc1" runat="server" ActiveTabIndex="0" OnClientActiveTabChanged="loadTabPanel"

Note this WILL NOT set the content for the initial tab.  For the tab you start with, you really should render that to begin with.  If you need to do this dynamically, you'll need to add some code to fire the activeTabChanged event on the TabContainer when it loads.  The JavaScript is fairly straight forward, but I won't paste it in here.  You can grab it from the project.

<

script type="text/ecmascript" src="OnDemandTabs.js"/>

Test it - we're done!  When the active tab changes, the UpdatePanel will fire and we'll go back to the server.  Note how this is set up so you can do it for N tabs - just keep using TabButtonX/TabContentX as the naming pattern and it'll work.

 

We can even add an UpdateProgress here to make it look nice, though on the local machine we'll probably never see it.

<asp:UpdateProgress id="UpdateProgress1" runat="server" AssociatedUpdatePanelID="UpdatePanel1">

<ProgressTemplate>Loading...</ProgressTemplate>

</asp:UpdateProgress>

 Presto.  Hope that helps.  Full project attached.  Works in all browsers.

OnDemandTabs.zip