Creating a jQueryUI Accordion with a Data View Web Part

We can do all sorts of fun stuff that makes the user experience (UX) in SharePoint far better than it is out of the box. One of those things is to use jQueryUI widgets like an accordion to put a large amount of content on the page, but broken into categorized, consumable chunks. Most people are very accustomed to using things like accordions from other Web sites they visit regularly, and even if they aren’t things like accordions seem to make sense quickly.

I had forgotten about it, but I did a post earlier this year where I showed how Carlos Nunes-Ueno approached this. It turns out that our XSL looks similar, but here is another example based on an accordion I recently set up myself.

To start building this, we created two lists. The first list, which we called Accordion Headers, contains the names of the accordion panels plus a column we can use to adjust the order of the panels.

clip_image002

The other list, called Accordion Content, contains the accordion panel content, and has a Lookup column into the Title in the Accordion Headers list. We also pulled the Order column from the Accordion Headers list in with the header name. There are several other columns in this list that we used to construct the content for each accordion panel.

clip_image002[4]

Once the lists were in place and populated, I just added a Data View Web Part (DVWP) to a page with the Accordion Content list as its DataSource.

If you look at the jQueryUI documentation page for the accordion widget, you can see that it wants the markup to look like this:

<div id="accordion">
 <h3><a href="#">First header</a></h3>
 <div>First content</div>
 <h3><a href="#">Second header</a></h3>
 <div>Second content</div>
</div>

The XSL is simple, but you have to roll your own; SharePoint Designer knows nothing about how to structure the rendered markup for this. To do this with the Accordion Content list, the XSL looked like this. Our panels contain unordered lists of links.

<xsl:template match="/" xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:SharePoint="Microsoft.SharePoint.WebControls">
  <xsl:call-template name="AccordionSetup"/>
</xsl:template>

<xsl:template name="AccordionSetup">
  <xsl:variable name="Rows" select="/dsQueryResponse/Rows/Row"/>
  <div id="left-accordion" style="width: 300px;">
    <xsl:for-each select="$Rows">
      <xsl:sort select="@AccHeading_x003a_Order" data-type="number"/>
      <xsl:sort select="@Order" data-type="number"/>
      <xsl:call-template name="AccordionPanels">
        <xsl:with-param name="Rows" select="$Rows"/>
      </xsl:call-template>
    </xsl:for-each>
  </div>
</xsl:template>

<xsl:template name="AccordionPanels">
  <xsl:param name="Rows"/>
  <xsl:variable name="NewHeading" select="ddwrt:NameChanged(string(@AccHeading.), 0)"/>
  <xsl:if test="string-length($NewHeading) &gt; 0">
    <h3>
      <a href="#{substring-before(@AccHeading., ';#')}">
        <xsl:value-of select="substring-after(@AccHeading., ';#')"/>
      </a>
    </h3>
    <div>
      <ul>
        <xsl:variable name="PanelRows" select="$Rows[@AccHeading. = current()/@AccHeading.]"/>
        <xsl:for-each select="$PanelRows">
          <xsl:call-template name="AccordionPanelContent"></xsl:call-template>
        </xsl:for-each>
      </ul>
    </div>
  </xsl:if>
</xsl:template>

<xsl:template name="AccordionPanelContent">
  <li>
    <xsl:value-of select="@Title"/> - <a href="{@ContentLink}"><xsl:value-of select="@ContentLink.desc"/></a>
  </li>
</xsl:template>

It’s pretty simple, really, and what we ended up with is a nicely organized, list-driven accordion which is easy to use and easy to maintain. No developer required to make changes whatsoever. It’s a win-win all around.

clip_image002[6]

<UPDATE dateTime=”2011-11-03T09:26″>

It occurred to me, though no one complained, that I hadn’t shown the jQuery to activate the accordion. Getting the markup right is really the hard part, as the jQuery can be as simple as this:

$("#left-accordion").accordion();

In this particular case, we set a few options as well:

$("#left-accordion").accordion({
  active:false,
  autoHeight: false,
  collapsible: true
});

I’ll leave it to you to check the jQueryUI docs to see what each option does.

</UPDATE>

Similar Posts

48 Comments

  1. Mark, great post – I have created very similar navigation in the past – your post highlighted a couple new ideas!!

    p.s. I think you may have a typo in your code example – in the AccordianSetup template you pass operation to AccordianRows template (but your exaple does not show this template – should this be AccordianPanels?

  2. Marc, great stuff, thanks.

    Quick question on what this sentence means:

    We also pulled the Order column from the Accordion Headers list in with the header name

    How does the Order column in the Accordian Content list relate back to the Order column in the Accordian Header list? I understand that the AccHeading Column is a lookup, but the Order column in the Content list seems to be unrelated to the Order column in the Header list. Am I missing something?

    1. David:

      We had two Order columns: one in the Accordion Header list and one in the Accordion Content list. We used the former to order the accordion headers and the latter to order the content within each accordion panel.

      M.

      1. Thanks for the quick response Mark.

        So is the Order column from the Header list used as the ID column for the AccHeading lookup column?

        I’m not clear on how you were able to get this value in the DVWP if the AccordianContent list is the data source:
        @AccHeading_x003a_Order

        1. David:

          In SharePoint 2010, you can pull additional column values along with the Lookup column value. In this case, the AccHeading Lookup column is a lookup value from the Accordion Heading list’s Title column. In the list settings, we also ticked the box for Order, so it comes along with the Lookup column value as AccHeading:Order.

          Hopefully this makes it clearer.

          M.

  3. Hi Marc,

    Is it possible to put WebpartZone html in content section of accordion? is there any other approach to do this (adding Webpart Zones in Content Section)

    Regards,
    Swati

      1. Hi Mark,

        Thanks for reply.Can we make this accordion dynamic (like number of panels in accordion and the order of panels ) ? This was possible in above example with Listitems.

        Regards
        Swati

        1. Swati:

          You won’t be able to make the number of Web Part Zones dynamic because you’d be creating the dynamic panels in a DVWP, which can’t contain WPZs. Can you explain more about what you’re trying to accomplish?

          M.

  4. I am very inexperienced so you may need to walk me through this. I have set up the DVWP using the Accordion Content list as a date source. Next I highlight the webpart and insert the above XSL where exactly in the code? After that I create a js file referencing the jquery library and jquery ui files, with the above code to call the accordion function, and link that file through a content editor on the page? Thanks for the help.

      1. Ok, when I do that, the list seems to disappear in the design view. Is there something wrong with the way I am inserting the code, or will it be fixed once I call the jquery?

        1. No, that doesn’t sound right. However, you should try saving the page and loading it in the browser.

          There’s all sorts of variability in all of this, so it’s pretty hard to debug it from here.

          M.

          1. Thanks for the quick reply. I appreciate the effort! When I reload it in the browser it says “Web Part Error: Type ‘Microsoft.Sharepoint.WebPartPages.XsltListViewWebPart’ does not have a public property named ‘template'”. I’m wondering if it has to do with where exactly I insert the code. I’ve tried leaving the opening and closing tags intact, and I’ve tried getting ridding of them.

            1. OK, then you haven’t added a DVWP to the page, but an XLVWP. I don’t have SharePoint Designer handy right now, but do some Bingling and you should be able to find a description of how to end up with a DVWP instead.

              M.

              1. Ok I have DVWP now, with the same problem, when I replace the XSL the list disappears. I guess I will do some more reading around to see what I can do. Thanks for the help.

  5. Hi Marc! This was excellent. I am having some difficulty wrapping my head around the XSL. I was able to get what you have done working, but I would like to take it a step forward and format it either as a table with single rows or where each entry has borders.

    Is there a decent way to do this?

    Thanks so much!

  6. Hi Marc

    I’ve tried to implement your code and its nearly working I’m getting the heading and the content but the links do show and hide the content, any help would be appreciated. I’ve added the jquery links on the page using a cqwp could this be causing my links not to work?

  7. Mark, thanks for this posting. I’m almost there, and have a stupid question. Where bout do I put the jquery trigger? … sorry new to the (much needed accordion AND DVWP)

    /RDN

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.