When you think ASP, think...
Recent Articles
All Articles
ASP.NET Articles
ASPFAQs.com
Message Board
Related Web Technologies
User Tips!
Coding Tips
Search

Sections:
Book Reviews
Sample Chapters
Commonly Asked Message Board Questions
JavaScript Tutorials
MSDN Communities Hub
Official Docs
Security
Stump the SQL Guru!
Web Hosts
XML
Information:
Advertise
Feedback
Author an Article

ASP ASP.NET ASP FAQs Message Board Feedback
 
Print this Page!
Published: Wednesday, September 15, 2004

Creating Collapsible Detail Regions in a Repeater

By Scott Mitchell


Introduction


There are many ways to make a Web page unusable, from cluttered content to poor page layout to non-contrasting colors. One of the simplest ways to quickly render a page unusable is to present "data overload." A page that suffers from data overload is one that displays way too much information on a single page. For example, one that shows dozens of database records, with each record having dozens of fields.

There are many ways to help alleviate data overload, such as enabling paging of the data, or displaying only a subset of the database fields and providing a "Details" link for each record that, when clicked, displays the multitude of fields for the specific record. Another approach - which is surprisingly easy and, in my opinion, looks very professional - is to have data displayed in a collapsible format. By this I mean showing only a short caption for each database record, and hiding the details. To display the details, the user can click the caption, which will cause the details to be automatically displayed. All of this can be accomplished with a bit of clever DHTML and client-side JavaScript. (To get a sneak peak at the finished product, check out this live demo.)

In this article we'll examine how to display data in collapsible manner using a Repeater. By the end of this article you'll have the complete code and concepts for creating such a slick user interface yourself, and helping prevent against data overload in your Web applications.

- continued -

Showing and Hiding Content Through Client-Side Actions


For several years now - since the 4.x browser versions - it is quite possible (and relatively easy) - to have contents on a Web page be hidden or displayed based on a client-side action. For example, the contents of a <div> tag can be dynamically hidden in response to clicking a button, or the contents of a paragraph (that is, the contents inside the <p> tag), could be displayed when mousing over some other content region.

The "trick" behind showing and displaying data in a Web page is setting the element's display and visibility style settings. The following HTML snippet shows how to hide and display content by toggling these style settings for a particular HTML element with the click of a button; you can test out the HTML in the interactive demo following the code snippet.

<script language="JavaScript">
  function showHideContent(id, show)
  {
    var elem = document.getElementById(id);
    if (elem) 
    {
      if (show) 
      {
        elem.style.display = 'block';
        elem.style.visibility = 'visible';
      } 
      else
      {
        elem.style.display = 'none';
        elem.style.visibility = 'hidden';
      }
    }
  }        
</script>

<div id="someRegion">
  This text will be displayed or hidden when clicking the appropriate button below...
</div>

<input type="button" value = "Hide Content"
   onclick="showHideContent('someRegion', false);">
<input type="button" value = "Show Content"
   onclick="showHideContent('someRegion', true);">

Interactive Demo


This text will be displayed or hidden when clicking the appropriate button below...

As the above interactive demo illustrates, with a bit of client-side JavaScript you can change an HTML element's display and visiblity style settings, thereby dynamically showing or hiding the element. This is all done on the client-side, and does not require a postback. Note that to modify the style for an element we use the document.getElementById(id) method to retrieve the element by its ID; next, we set its appropriate properties. A thorough discussion on DHTML is far beyond the scope of this article, especially since there are plenty of great resources on this topic all around the Web.

Displaying Details in a Collapsible Interface


With a little effort this concept can be applied to the data displayed in an ASP.NET Web page. If you have a page that needs to show a lot of fields per record, the page can quickly become unwieldy. For example, imagine that we wanted to display information about the FAQs at ASPFAQs.com. Each FAQ is stored as a record in the tblFAQs table, containing information such as the FAQ, the answer, the number of times the FAQ has been viewed, who submitted the FAQ, and other pertinent information. We may want to display this information on an ASP.NET Web page using a Repeater. To accomplish this we could use the following Repeater syntax:

<asp:Repeater id="rptFAQs" runat="server">
   <ItemTemplate>
     <h2><%# DataBinder.Eval(Container.DataItem, "Description") %></h2><br />
     <b>Submitted By:</b> <%# DataBinder.Eval(Container.DataItem, "SubmittedByName") %><br />
     <b>Views:</b> <%# DataBinder.Eval(Container.DataItem, "ViewCount", "{0:d}") %><br />
     <b>FAQ:</b><br />
     <%# DataBinder.Eval(Container.DataItem, "Answer") %>
   </ItemTemplate>
</asp:Repeater>
[View a Live Demo!]

As the live demo illustrates, this leads to a bit of information overload, in large part because the answer for each FAQ can be quite lengthy.

Rather than display this large amount of data for each FAQ, a more manageable user interface would be to display just the FAQ questions, making them clickable. When a user clicked such a header, it would expand to show the details for the FAQ, using client-side DHTML/JavaScript. This can be accomplished with a bit of clever markup in the Repeater's ItemTemplate.

First, we need to create two <div>s for each record: one that displays the FAQ question, and one that has the detailed information (the answer, the view count, and so on). The first <div> will always be displayed for each record and, when clicked, will toggle the display for its related details <div>. In order to accomplish this, each <div> will need to be given a unique id value, which will be referenced in a client-side JavaScript function that toggles the visibility. Specifically, each FAQ question <div> will have the id hindex, where index is the ItemIndex of the Repeater item. Each details <div> will have the id dindex.

The following shows the ItemTemplate for our collapsible Repeater, along with some CSS classes to improve the appearance and the client-side JavaScript function to toggle the display.

<script language="JavaScript">
  function ToggleDisplay(id)
  {
    var elem = document.getElementById('d' + id);
    if (elem)
    {
      if (elem.style.display != 'block')
      {
        elem.style.display = 'block';
        elem.style.visibility = 'visible';
      }
      else
      {
        elem.style.display = 'none';
        elem.style.visibility = 'hidden';
      }
    }
  }
</script>

<style>
    .header { font-size: larger; font-weight: bold; cursor: hand; cursor:pointer;
               background-color:#cccccc; font-family: Verdana; }
    .details { display:none; visibility:hidden; background-color:#eeeeee;
               font-family: Verdana; }
</style>

<asp:Repeater id="rptFAQs" runat="server">
   <ItemTemplate>
     <div id='h<%# DataBinder.Eval(Container, "ItemIndex") %>' class="header"
          onclick='ToggleDisplay(<%# DataBinder.Eval(Container, "ItemIndex") %>);'>
       <%# DataBinder.Eval(Container.DataItem, "Description") %>
     </div>
        
     <div id='d<%# DataBinder.Eval(Container, "ItemIndex") %>' class="details">
       <b>Submitted By:</b> <%# DataBinder.Eval(Container.DataItem, "SubmittedByName") %><br />
       <b>Views:</b> <%# DataBinder.Eval(Container.DataItem, "ViewCount", "{0:d}") %><br />
       <b>FAQ:</b><br />
       <%# DataBinder.Eval(Container.DataItem, "Answer") %>
     </div>
   </ItemTemplate>
</asp:Repeater>
[View a Live Demo!]

There are a couple of things to note in the code. First, notice how the two <div> elements in each ItemTemplate are given an id that includes the RepeaterItem's index value. This index value is taken from the ItemIndex property. Additionally, the header <div> as a client-side onclick event that calls the ToggleDisplay() JavaScript function, passing in the index of the row whose header was clicked. This JavaScript function then toggles the display and visibility style settings for that row's details <div>.

To see the collapsible Repeater in action, be sure to check out the live demo. Hopefully you'll agree that the page is much cleaner and no longer suffers from information overload.

Happy Programming!

  • By Scott Mitchell



  • ASP.NET [1.x] [2.0] | ASPMessageboard.com | ASPFAQs.com | Advertise | Feedback | Author an Article