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.
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.
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) > 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.
<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>
My headers are repeating and include the same content over and over. For example: I have a group ‘Red’ and a group ‘Green’. It will display the accordion headers as Green (with content); Red (with content); Green (with content) and continue to repeat. How do I make the headers only appear once in the accordion?
Awesome! Big thanks to you and Carlos. I was struggling to get this to work for a couple days but I realized I had neglected to include a script tag! duh!
Jeff:
It’s always something little that sends us off into la-la-land!
M.
Hi Mark, thank you for the useful post. After adding the code above, I have only the first header and the first content link from my lists displayed. Could you advice how make all of the headers and content links to appear? Thanks!
Rita:
Are you sure that .accordion() has fired properly? Also, check that your markup is valid. You may be missing a closing div tag or something.
M.
Marc, thank you for your prompt response. I re-added the Data View web part, selected ALL the fields to be inserted this time, updated the XSL markup and now all the headers and content are loading. However, the accordion formatting is gone. It’s showing up as an unordered list. I have a reference to my .js file () and my .js file has: $(function () {
$(“#left-accordion”).accordion(); }); This used to work, when I had only one header and first link displayed. What am I missing? Please advice. Thank you very much for your time and help!
Marc, my accordion is working now. My .js file had an error, non-related to the accordion, which was precluding accordion UI to load. Thanks again for the great post! -Rita
I have pulled an all-nighter trying to accomplish using JQuery Accordian within EasyTabs. Everything works fine, with the exception after the initial save, the values of the fields disappear except for @Title. I have a list that has @Title, @Question & @Answer. For what ever reason, the other fields just stop responding – but they always show in the Design view of SPD. Just doesn’t make sense.
Eli:
Keep in mind that JavaScript doesn’t run in SharePoint Designer. You’re just seeing the data.
Make sure that you store the code in an external file so that you’re not editing the page in the UI directly.
M.
Exactly what I needed and your article was very easy to follow. Thanks so much!!
Hi Marc,
Everything working fine,
But I am not able to increase RowLimit more than 10.
I want to show all list Item in accordion.
Marc please help me to resolve this issue.
You’ve probably got a RowLimit set in your CAML. You should be able to change it.
M.
Thanks Marc,
I update MaximumRows to 30 in DVWP
<SharePoint:SPDataSource runat="server"
Thanks,
Digambar K
Where does the jQuery go?
How are you linking the file? It does not work with a CEWP. If so, how?
@MAT: I did this by editing the page directly in SharePoint Designer. There’s no other way to change the XSL in a DVWP effectively.
M.
I changed the xsl in the dataview webpart but how do I implement the jQuery? How are you inserting it into the xsl?
The content and header shows up in the browser but they do not show and hide on header click.Any help would be appreciated.
@imadeveloper:
It sounds like the script isn’t acting on the markup properly. If the accordion is created, then the set up is right, but the options may not be. You’ll probably need to do some debugging in the browser.
M.