Customize the rendering of a List View in Sharepoint 2010: Displaying List Items in Accordion


The creation of non standard presentations for Lists/Libraries  is a fairly common  scenario and using the XSLT List View Web Part (XLV) possibilities that can be achieved pretty easily.
Let’s take a look how to render list of question and answers using Accordion Menu in SharePoint. Actually the idea for this post appeared after posting  of corresponding question on StackOverflow.
So, let’s discuss how it could be accomplished using XLV. For Accordion we will utilize jQuery UI library.



FAQ Custom List

First of all, let us define where  the questions and answers (FAQ) we’ll be stored. For this we will use Custom List with Content Type.

<ContentType ID="0x0100fb1027dc96a44bf280f6cb823a8da5ae"
Description="FAQ Content Type"
<FieldRef Name="LinkTitle" ID="{82642ec8-ef9b-478f-acf9-31f7d45fbc31}" DisplayName="Question" Sealed="TRUE"/>
<FieldRef Name="LinkTitleNoMenu" ID="{bc91a437-52e7-49e1-8c4e-4698904b2b6d}" DisplayName="Question" Sealed="TRUE"/>
<FieldRef Name="Title" ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" DisplayName="Question" Sealed="TRUE"/>
<FieldRef ID="{b0747420-54bc-41b2-a1b3-8432f2dbdc70}" Name="Answer"/>

Custom View for arranging items using jQuery UI Accordion

After creating Custom List we add new View for displaying Accordion for FAQ items

<View BaseViewID="10" Type="HTML" WebPartZoneID="Main" DisplayName="Accordion" DefaultView="FALSE" SetupPath="pages\viewpage.aspx" ImageUrl="/_layouts/images/generic.png" Url="Accordion.aspx">
<Toolbar Type="Standard" />
<XslLink Default="TRUE">FAQ.xsl</XslLink>
<RowLimit Paged="TRUE">30</RowLimit>
<FieldRef Name="Title" ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" DisplayName="Question" Sealed="TRUE"/>
<FieldRef Name="Answer" ID="{b0747420-54bc-41b2-a1b3-8432f2dbdc70}"></FieldRef>
<FieldRef Name="ID"></FieldRef>

XSLT style sheet for rendering Accordion View

XSLT style sheet for FAQ List is intended for the following purposes:

  • loading jQuery Core and UI Libraries
  • rendering list items using layout as specified for Accordion menu
  • initializing and rendering Accordion for List items

<xsl:stylesheet xmlns:x=""
version="1.0" exclude-result-prefixes="xsl msxsl ddwrt x d asp __designer SharePoint ddwrt2"
<xsl:import href="/_layouts/xsl/main.xsl"/>
<xsl:output method="html" indent="no"/>
<xsl:template match="View[@BaseViewID='10']" mode="full" ddwrt:ghost="always">
<tr class="ms-viewheadertr"></tr>
<div id="accordionFAQ">
<xsl:apply-templates select="." mode="RenderView" />
<xsl:apply-templates mode="footer" select="." />
<xsl:template mode="Item" match="Row[../../@BaseViewID='10']" ddwrt:ghost="always">
<xsl:param name="Fields" select="."/>
<xsl:param name="Collapse" select="."/>
<xsl:param name="Position" select="1"/>
<xsl:param name="Last" select="1"/>
<xsl:variable name="thisNode" select="."/>
<xsl:value-of select="$thisNode/@Title" />
<xsl:value-of select="$thisNode/@Answer" disable-output-escaping="yes" />
<xsl:template name="FAQViewOverride" mode="RootTemplate" match="View[List/@TemplateType=11999]" ddwrt:dvt_mode="root">
<link rel="stylesheet" href="" />
<script src=""></script>
<script src=""></script>
$(function() {
$( "#accordionFAQ" ).accordion();
<xsl:call-template name="View_Default_RootTemplate"/>

view raw


hosted with ❤ by GitHub

Using jQuery UI Accordion

jQuery Core and UI libraries are injected during XSLT style sheet processing. After JavaScript files which hosted on Microsoft CDN are loaded, jQuery UI Accordion is initialized for items.

<xsl:template name="FAQViewOverride" mode="RootTemplate" match="View[List/@TemplateType=11999]" ddwrt:dvt_mode="root">
<link rel="stylesheet" href="" />
<script src=""></script>
<script src=""></script>
$(function() {
$( "#accordionFAQ" ).accordion();
<xsl:call-template name="View_Default_RootTemplate"/>


FAQ List Accordion View rendered in XLV is shown below on picture

FAQ Accordion View


Visualizing organizational structure in SharePoint with Google Chart Tools

Sometimes in SharePoint we need to visualize hierarchical  data as organizational chart. Prerequisites: not to use  Flash or Silverlight technologies here.

So, in our scenario for storage of organization structure will be used SharePoint List based on Custom List , for rendering engine  Google Chart Tools.


First, let’s take a look at list’s schema for storing organizational structure

Name Type Description
ParentOrgElement Lookup Used for parent/child relationship
OrgDescription Note Display text for chart box
OrgAdditionalProperties Note Visual behavior for chart box

From Google Charts library we’ll use Organizational Chart package only.

1. Google Charts Tools loading and package initialization

function visualizeOrgChart(orgChartProperties) {
google.load('visualization', '1', { packages: ['orgchart'] });
google.OrgChartData = orgChartProperties;

2. Fetch data using SharePoint Web Service from list that contains organizational structure

function loadOrgChart() {
var soapEnv =
"<soapenv:Envelope xmlns:soapenv=''&gt; \
<soapenv:Body> \
<GetListItems xmlns=''&gt; \
<listName>" + google.OrgChartData.ListName + "</listName> \
<viewFields> \
<ViewFields> \
<FieldRef Name='" + google.OrgChartData.TitleFieldName + "' /> \
<FieldRef Name='" + google.OrgChartData.TooltipFieldName + "' /> \
<FieldRef Name='" + google.OrgChartData.ParentFieldName + "' /> \
<FieldRef Name='" + google.OrgChartData.StyleFieldName + "' /> \
</ViewFields> \
</viewFields> \
</GetListItems> \
</soapenv:Body> \
url: L_Menu_BaseUrl + "/_vti_bin/lists.asmx",
type: "POST",
dataType: "xml",
data: soapEnv,
complete: onOrgChartDataLoaded,
contentType: "text/xml; charset=\"utf-8\""

view raw


hosted with ❤ by GitHub

3. Bind data source and draw chart

function onOrgChartDataLoaded(orgChartData, status) {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Name');
data.addColumn('string', 'Parent');
data.addColumn('string', 'ToolTip');
var chartFieldNames = { Title: generateOwsFieldName(google.OrgChartData.TitleFieldName),
Tooltip: generateOwsFieldName(google.OrgChartData.TooltipFieldName),
Parent: generateOwsFieldName(google.OrgChartData.ParentFieldName),
Properties: generateOwsFieldName(google.OrgChartData.StyleFieldName)
var orgChartRowProperties = {};
var orgChartDataRows = [];
var orgChartResult = ($.browser.msie ? orgChartData.responseXML : orgChartData.responseText);
$(orgChartResult).find("z\\:row").each(function (rowIndex) {
var orgChartRow = [];
//if ($(this).attr(chartFieldNames.Layout) == undefined)
orgChartRow[0] = $(this).attr(chartFieldNames.Title);
//else {
// orgChartRow[0] = { v: $(this).attr(chartFieldNames.Title), f: $(this).attr(chartFieldNames.Layout) };
orgChartRow[1] = ($(this).attr(chartFieldNames.Parent) != undefined ? $(this).attr(chartFieldNames.Parent).split(';#')[1] : '');
orgChartRow[2] = $(this).attr(chartFieldNames.Tooltip);
if ($(this).attr(chartFieldNames.Properties) != undefined) {
orgChartRowProperties[rowIndex] = parseChartRowProperties($(this).attr(chartFieldNames.Properties));
orgChartDataRows[orgChartDataRows.length] = orgChartRow;
$.each(orgChartRowProperties, function (rowIndex, rowProperty) {
data.setRowProperties(parseInt(rowIndex), rowProperty);
var chart = new google.visualization.OrgChart(document.getElementById('orgChartCanvas'));
chart.draw(data, { allowHtml: true, allowCollapse: true });


Result page with Org Structure rendered as Chart in List View


Validate SharePoint People Editor in SharePoint 2010


Validation of SharePoint PeopleEditor WebControl on the client-side is often required. On server side validation is supported, see AllowEmpty and  ValidatorEnabled properties for details, but the lack of client side validation makes it inconvenient for scenarios where client side validation is mandatory. So let’s discuss some techniques how it could be achieved.

Server-Side Validation

In order to enable/disable validation for Entity Editor based controls (like People Editor) the following properties should be specified in combination:

For example, the  code below demonstrates how to disable empty values:


Client-Side Validation

Let’s start with the simple method that allows to check if PeopleEditor control is not empty.

The code below demonstrates  how to validate if SharePoint PeopleEditor control value is not empty

function validateIfPeopleEditorNotEmpty(peId) {
var $pe = $("#" + peId);
var $peValHolder = $pe.find("input[id$='hiddenSpanData']");
return ($peValHolder.val().length > 0);

It can be used in the following scenarios:

Since jQuery is commonly used  in SharePoint front-end development, it validation  capabilities could be used  for  PeopleEditor,  for example  jQuery Validation plugin. The code below demonstrates how validation rule that allow us to verify if PeopleEditor value is not empty, may look like.

//People Editor Validator with jQuery Validation plugin
function validatePeopleEditor(peId,messageText)
var $pe = $("#" + peId);
var $peValHolder = $pe.find("input[id$='hiddenSpanData']");
$peValHolder.rules("add", {
required: true,
messages: {
required: messageText


Initializing SharePoint People Editor using JavaScript in SharePoint 2010

Sometimes SharePoint PeopleEditor WebControl need to be initialized on the client side.

Initialize People Editor control

//Init People Picker
//peoplePickerId – SharePoint People Editor ClientID
//pickerEntityXml – PickerEntity in xml (see method ToXmlData for class PickerEntity)
function initPeoplePickerBox(peoplePickerId, pickerEntityXml) {
var $pe = $("#" + peoplePickerId);
var entityProps = {LoginName: pickerEntityXml.attr("Key"),
UserName: pickerEntityXml.attr("DisplayText"),
Description: pickerEntityXml.attr("Description")};
var entityExtendedProps = pickerEntityXml.find("ArrayOfDictionaryEntry");
var $peData = $pe.find("input[id$='hiddenSpanData']");
var $peDisplayArea = $pe.find("div[id$='_upLevelDiv']");
var displayData = "<span id='span{LoginName}' iscontenttype='true' tabindex='-1' class='ms-entity-resolved' contenteditable='false' title='{LoginName}'>" +
" <div style='display:none;' id='divEntityData' key='{LoginName}' displaytext='{UserName}' isresolved='True' description='{LoginName}'>" +
" <div data='{PickerEntityData}'></div>" +
" </div>" +
" <span id='content' tabindex='-1' contenteditable='false' onmousedown='onMouseDownRw(event);' oncontextmenu='onContextMenuSpnRw(event,ctx);'>{UserName}</span>" +
var pickerEntityData = convertFromXML(entityExtendedProps[0]);
displayData = displayData.replace(/{LoginName}/g, entityProps.LoginName);
displayData = displayData.replace(/{UserName}/g, entityProps.UserName);
displayData = displayData.replace('{PickerEntityData}', pickerEntityData);

Clear People Editor control

//Clear People Picker
//peoplePickerId – SharePoint People Editor ClientID
function clearPeoplePickerBox(peoplePickerId) {
var $pe = $("#" + peoplePickerId);
var $peData = $pe.find("input[id$='hiddenSpanData']");
var $peDisplayArea = $pe.find("div[id$='_upLevelDiv']");