HOW TO: Create a Table-with-Headers List Item Style for your CQwp

2012-12-21 MV to All: SharePoint 2010 has our beloved Content (by) Query Web Part (CQwp for short), but even after years in the SharePoint stable this powerful web part continues to be all-but-neglected by Microsoft in terms of adding much-needed common list item styles. For example, far & away THE most common request clients have for the CQwp is TABULAR output with COLUMN HEADINGS. I kid you not – They DO expect it, and it’s NOT built-in. Go figure. So here’s how to do it, and luckily in SharePoint 2010 it’s easier to do than past versions; you NO longer need to export the .webpart file, tweak the code and re-import it in order to define more “slots” (web part property form fields) into which you’ll add the desired table columns.

BROWSE to the top of your Site Collection
SELECT Site Actions > View All Site Content
NAVIGATE into Style Library > XSL Style Sheets
=> all the key XSL files are there which control both group headings and individual list item style sheets, all written in XSL instead of CSS

KEY FILES:
Header.xsl – this file contains the set of built-in Group Heading styles used by the CQwp. Each XSL block actually references its own CSS style, and that’s something we’ll leverage;
ItemStyle.xsl – this file contains the set of built-in List Item Styles used by teh CQwp. Each XSL block creates a views variables, then builds pretty much the same useless arrangement of these items.

GOAL:
Somehow modify what’s available to us in the CQwp in order to arrive at a table-like output, complete with column headings.

CHALLENGES:
1. A table is made up of both items which DO repeat, and a set of headings which DON’T repeat. Therefore editing only the ItemStyle.xsl file WON’T help with displaying COLUMN headings.
2. Column headings shouldn’t really be hard-coded, as that would make them useful only on a SINGLE instance of a CQwp.
3. SharePoint generates each list item as its OWN TABLE (e.g. <table><tr><td>field1</td><td>field2</td><td>field3</td></tr></table>). I shit you not.

STRATEGY:
1. CREATE a SET of tables inside the CQwp, each having IDENTICAL dimensions, so they literally “stack up” and APPEAR to The User as if they were a SINGLE table;
2. CREATE a Column Heading table first, by customizing the Header.xsl file to introduce a NEW Group Heading style;
3. CREATE an Item Row table next, by customizing the ItemStyle.xsl file to introduce a NEW List Item Style which will be repeated for the rest of the rows forming our pseudo-table.

BEST PRACTICES:
0. DO NOT USE SharePoint Designer 2010 for editing; Call me superstitious, but I fear it will EDIT (read “add code”) to these files. Instead save copies of the XSL files to your desktop, edit them with NotePad++, and re-upload them to the Style Library, thereby overwriting the file that’s there;
1. CREATE a BACKUP of the original Header.xsl, named Header-ORIGINAL-2012-12-20MV.xsl, and upload it back to the Style Library BEFORE editing the Header.xsl file there;
2. CREATE a BACKUP of the original ItemStyle.xsl, named ItemStyle-ORIGINAL-2012-12-20MV.xsl, and upload it back to the Style Library BEFORE editing the ItemStyle.xsl file there.

Here’s a screenshot:

SAMPLE CODE:
Header.xsl:


</xsl:template>
  <xsl:template name="Whitespace" match="*[@GroupStyle='Whitespace']" mode="header">
    <div>
        <xsl:text>&#xA;</xsl:text>
    </div>
  </xsl:template>

<!-- 2012-12-20 MV JC: this custom GroupHeadingStyle is meant for use with the MasterDocumentCQwp... -->
  <xsl:template name="MasterDocumentHorizontalGroupStyle" match="*[@GroupStyle='MasterDocumentHorizontalGroupStyle']" mode="header">
    <div>
  <table width="100%">
   <tr>
    <td width="25%">
     <xsl:value-of select="name(@Title)" />
    </td>
    <td width="10%">
     <xsl:value-of select="name(@ForDE)" />
    </td>
    <td width="10%">
     <xsl:value-of select="name(@ForFE)" />
    </td>
    <td width="10%">
     <xsl:value-of select="name(@ForPE)" />
    </td>
    <td width="10%">
     <xsl:value-of select="name(@ForPM)" />
    </td>
    <td width="10%">
     <xsl:value-of select="name(@ForOther)" />
    </td>
    <td>
     <xsl:value-of select="name(@URL)" />
    </td>    �
   </tr>
  </table>
    </div>
  </xsl:template>
</xsl:stylesheet>

ItemStyle.xsl


  </div>
    </xsl:template> 

<!-- 2012-12-20 MV JC: The following is a custom ListItemStyle developed for general use at AT&T Consulting...-->
<xsl:template name="ATTCustomHorizontalItemStyle" match="Row[@Style='ATTCustomHorizontalItemStyle']" mode="itemstyle">
        <xsl:variable name="SafeLinkUrl">
            <xsl:call-template name="OuterTemplate.GetSafeLink">
                <xsl:with-param name="UrlColumnName" select="'LinkUrl'"/>
            </xsl:call-template>
        </xsl:variable>
        <xsl:variable name="SafeImageUrl">
            <xsl:call-template name="OuterTemplate.GetSafeStaticUrl">
                <xsl:with-param name="UrlColumnName" select="'ImageUrl'"/>
            </xsl:call-template>
        </xsl:variable>
        <xsl:variable name="DisplayTitle">
            <xsl:call-template name="OuterTemplate.GetTitle">
                <xsl:with-param name="Title" select="@Title"/>
                <xsl:with-param name="UrlColumnName" select="'LinkUrl'"/>
            </xsl:call-template>
        </xsl:variable>
        <div>
            <div>
    <table width="100%">
     <tr>
      <!-- MV: this cell contains the XSL to get the current XSL variables and format them into a linked title for the document... -->
      <td width="25%">
        <xsl:call-template name="OuterTemplate.CallPresenceStatusIconTemplate"/>
       <a href="{$SafeLinkUrl}" title="<a href="mailto:%7B@LinkToolTip">{@LinkToolTip</a>}">
         <xsl:if test="$ItemsHaveStreams = 'True'">
        <xsl:attribute name="onclick">
          <xsl:value-of select="@OnClickForWebRendering"/>
        </xsl:attribute>
         </xsl:if>
         <xsl:if test="$ItemsHaveStreams != 'True' and @OpenInNewWindow = 'True'">
        <xsl:attribute name="onclick">
          <xsl:value-of disable-output-escaping="yes" select="$OnClickTargetAttribute"/>
        </xsl:attribute>
         </xsl:if>
         <xsl:value-of select="$DisplayTitle"/>
       </a>
      </td>
      <td width="10%">
                   <xsl:value-of select="@ForDE" />
      </td>
      <td width="10%">
                   <xsl:value-of select="@ForFE" />
      </td>
      <td width="10%">
                   <xsl:value-of select="@ForPE" />
      </td>
      <td width="10%">
                   <xsl:value-of select="@ForPM" />
      </td>
      <td width="10%">
                   <xsl:value-of select="@ForOther" />
      </td>
      <td>
                   <xsl:value-of select="@URL" />
      </td>
     </tr>
    </table>
            </div>
        </div>
    </xsl:template>�
  <xsl:template name="HiddenSlots" match="Row[@Style='HiddenSlots']" mode="itemstyle">
    <div>
      <xsl:value-of select="@SipAddress" />
    </div>
    <div>
      <xsl:value-of select="@LinkToolTip" />
    </div>
    <div>
      <xsl:value-of select="@OpenInNewWindow" />
    </div>
    <div>
      <xsl:value-of select="@OnClickForWebRendering" />
    </div>
  </xsl:template>
</xsl:stylesheet>

USAGE:
BROWSE to a web page.
EDIT
ADD a CQwp
EDIT the web part
CONFIGURE any query you wish, but make sure  it returns SOMETHING before continuing configuration of the webpart
PRESENTATION SECTION
   CHOOSE Group By <site>; you MUST choose SOME grouping, or the actual Grouping Header style won’t even be called;
   CHOOSE your new Group Heading Style.�
   CHOOSE your  new List Item Style.
=> The CQwp will execute your query, and return results as a bunch of XML ready to have XSLT applied to it;
=> The CQwp will note that you’ve select SOME sort of grouping, so will then apply the selected GroupHeading Style to the query result XML. This will simply generate the column headings table a the top of the XML-becoming-HTML;
=> The CQwp will then apply the selected ListItem Style  to each “item” element of the result XML; this will generate each row of the “pseudo table”, directliy below each of the column headings.

Here’s a screenshot of the finished product:

Leave a Reply

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