Sharepoint – custom content query webpart header and footer
Let’s say you want a content query webpart with a custom header and/or footer. If you use groups, it’s kind of simple. Just specify the group style in the Content Query Tool Part.
But if you don’t want groups, that’s a hole new story.
Here’s a way to get around this problem:
The idea is this – on the item style, if it’s the first item, prepend some html as a header. if it’s the last item append some html as the footer.
So, create a new item style (in itemstyle.xsl) like the following one:
In ContentQueryMain.xsl, change the OuterTemplare.Body to the following:
In ContentQueryMain.xsl, change the OuterTemplare.CallItemTemplate to the following:
The end result will look something like this:

Now you can add a custom header and footer, and if there is no content, the header / footer will not show.
But if you don’t want groups, that’s a hole new story.
Here’s a way to get around this problem:
The idea is this – on the item style, if it’s the first item, prepend some html as a header. if it’s the last item append some html as the footer.
So, create a new item style (in itemstyle.xsl) like the following one:
| XML | | copy code | | ? |
| 01 | <xsl:template name="CustomHeaderAndFooter" match="Row[@Style='CustomHeaderAndFooter']" mode="itemstyle"> |
| 02 | <!-- Important: Add these 2 params --> |
| 03 | <xsl:param name="CurPos"/> |
| 04 | <xsl:param name="Last"/> |
| 05 | <xsl:variable name="DisplayTitle"> |
| 06 | <xsl:call-template name="OuterTemplate.GetTitle"> |
| 07 | <xsl:with-param name="Title" select="@Title"/> |
| 08 | <xsl:with-param name="UrlColumnName" select="'LinkUrl'"/> |
| 09 | </xsl:call-template> |
| 10 | </xsl:variable> |
| 11 | <!-- Important: Add this variable --> |
| 12 | <xsl:variable name="webpartStart"> |
| 13 | <xsl:if test="$CurPos = 1"> |
| 14 | <![CDATA[ |
| 15 | <div class="webpartHeader1">Some Header Text</div> |
| 16 | ]]> |
| 17 | </xsl:if> |
| 18 | </xsl:variable> |
| 19 | <!-- Important: Add this variable --> |
| 20 | <xsl:variable name="webpartEnd"> |
| 21 | <xsl:if test="$CurPos = $Last"> |
| 22 | <![CDATA[ |
| 23 | <div class="webpartFooter1">Some Footer text</div> |
| 24 | ]]> |
| 25 | </xsl:if> |
| 26 | </xsl:variable> |
| 27 | |
| 28 | <!-- Important: Add this line--> |
| 29 | <xsl:value-of select="$webpartStart" disable-output-escaping="yes"/> |
| 30 | |
| 31 | <div id="linkitem" class="item link-item"> |
| 32 | <xsl:call-template name="OuterTemplate.CallPresenceStatusIconTemplate"/> |
| 33 | <xsl:value-of select="$DisplayTitle"/> |
| 34 | </div> |
| 35 | |
| 36 | <!-- Important:Add this line--> |
| 37 | <xsl:value-of select="$webpartEnd" disable-output-escaping="yes"/> |
| 38 | |
| 39 | </xsl:template> |
| 40 | |
| 41 | |
In ContentQueryMain.xsl, change the OuterTemplare.Body to the following:
| XML | | copy code | | ? |
| 01 | <xsl:template name="OuterTemplate.Body"> |
| 02 | <xsl:param name="Rows" /> |
| 03 | <xsl:param name="FirstRow" /> |
| 04 | <xsl:param name="LastRow" /> |
| 05 | <xsl:variable name="BeginColumn1" select="string('<td id="column" width="')" /> |
| 06 | <xsl:variable name="BeginColumn2" select="string('%" valign="top">')" /> |
| 07 | <xsl:variable name="BeginColumn" select="concat($BeginColumn1, $cbq_columnwidth, $BeginColumn2)" /> |
| 08 | <xsl:variable name="EndColumn" select="string('</td >')" /> |
| 09 | <xsl:for-each select="$Rows"> |
| 10 | <xsl:variable name="CurPosition" select="position()" /> |
| 11 | <xsl:if test="($CurPosition >= $FirstRow and $CurPosition <= $LastRow)"> |
| 12 | <xsl:variable name="StartNewGroup" select="@__begingroup = 'True'" /> |
| 13 | <xsl:variable name="StartNewColumn" select="@__begincolumn = 'True'" /> |
| 14 | <xsl:choose> |
| 15 | <xsl:when test="$cbq_isgrouping != 'True'"> |
| 16 | <xsl:if test="$CurPosition = $FirstRow"> |
| 17 | <xsl:value-of disable-output-escaping="yes" select="$BeginColumn" /> |
| 18 | </xsl:if> |
| 19 | </xsl:when> |
| 20 | <xsl:when test="$StartNewGroup and $StartNewColumn"> |
| 21 | <xsl:choose> |
| 22 | <xsl:when test="$CurPosition = $FirstRow"> |
| 23 | <xsl:value-of disable-output-escaping="yes" select="$BeginColumn" /> |
| 24 | <xsl:call-template name="OuterTemplate.CallHeaderTemplate"/> |
| 25 | </xsl:when> |
| 26 | <xsl:otherwise> |
| 27 | <xsl:call-template name="OuterTemplate.CallFooterTemplate"/> |
| 28 | <xsl:value-of disable-output-escaping="yes" select="concat($EndColumn, $BeginColumn)" /> |
| 29 | <xsl:call-template name="OuterTemplate.CallHeaderTemplate"/> |
| 30 | </xsl:otherwise> |
| 31 | </xsl:choose> |
| 32 | </xsl:when> |
| 33 | <xsl:when test="$StartNewGroup"> |
| 34 | <xsl:call-template name="OuterTemplate.CallFooterTemplate"/> |
| 35 | <xsl:call-template name="OuterTemplate.CallHeaderTemplate"/> |
| 36 | </xsl:when> |
| 37 | <xsl:when test="$StartNewColumn"> |
| 38 | <xsl:choose> |
| 39 | <xsl:when test="$CurPosition = $FirstRow"> |
| 40 | <xsl:value-of disable-output-escaping="yes" select="$BeginColumn" /> |
| 41 | </xsl:when> |
| 42 | <xsl:otherwise> |
| 43 | <xsl:value-of disable-output-escaping="yes" select="concat($EndColumn, $BeginColumn)" /> |
| 44 | </xsl:otherwise> |
| 45 | </xsl:choose> |
| 46 | </xsl:when> |
| 47 | <xsl:otherwise> |
| 48 | </xsl:otherwise> |
| 49 | </xsl:choose> |
| 50 | <xsl:call-template name="OuterTemplate.CallItemTemplate"> |
| 51 | <xsl:with-param name="CurPosition" select="$CurPosition" /> |
| 52 | <!-- Important: Add This Line --> |
| 53 | <xsl:with-param name="LastRow" select="$LastRow"/> |
| 54 | </xsl:call-template> |
| 55 | <xsl:if test="$CurPosition = $LastRow"> |
| 56 | <xsl:call-template name="OuterTemplate.CallFooterTemplate"/> |
| 57 | <xsl:value-of disable-output-escaping="yes" select="$EndColumn" /> |
| 58 | </xsl:if> |
| 59 | </xsl:if> |
| 60 | </xsl:for-each> |
| 61 | </xsl:template> |
| 62 | |
| 63 | |
In ContentQueryMain.xsl, change the OuterTemplare.CallItemTemplate to the following:
| XML | | copy code | | ? |
| 01 | <xsl:template name="OuterTemplate.CallItemTemplate"> |
| 02 | <xsl:param name="CurPosition" /> |
| 03 | <!--Important: Add This Line --> |
| 04 | <xsl:param name="LastRow" /> |
| 05 | |
| 06 | <xsl:choose> |
| 07 | <xsl:when test="@Style='NewsRollUpItem'"> |
| 08 | <xsl:apply-templates select="." mode="itemstyle"> |
| 09 | <xsl:with-param name="EditMode" select="$cbq_iseditmode" /> |
| 10 | </xsl:apply-templates> |
| 11 | </xsl:when> |
| 12 | <xsl:when test="@Style='NewsBigItem'"> |
| 13 | <xsl:apply-templates select="." mode="itemstyle"> |
| 14 | <xsl:with-param name="CurPos" select="$CurPosition" /> |
| 15 | </xsl:apply-templates> |
| 16 | </xsl:when> |
| 17 | <xsl:when test="@Style='NewsCategoryItem'"> |
| 18 | <xsl:apply-templates select="." mode="itemstyle"> |
| 19 | <xsl:with-param name="CurPos" select="$CurPosition" /> |
| 20 | </xsl:apply-templates> |
| 21 | </xsl:when> |
| 22 | <xsl:otherwise> |
| 23 | <xsl:apply-templates select="." mode="itemstyle"> |
| 24 | <!-- Important: Add These 2 Lines --> |
| 25 | <xsl:with-param name="CurPos" select="$CurPosition" /> |
| 26 | <xsl:with-param name="Last" select="$LastRow" /> |
| 27 | </xsl:apply-templates> |
| 28 | </xsl:otherwise> |
| 29 | </xsl:choose> |
| 30 | </xsl:template> |
| 31 | |
The end result will look something like this:

Now you can add a custom header and footer, and if there is no content, the header / footer will not show.