CQWP: 30 Tips #7, Group Ordering

 

On many occasions you’ll want to group items under a header, but control the order of the group display.  The problem here is that when you select your group by field, you can only sort that group alphabetically ascending or descending.  A quick fix is to prepend a numeric value to the field your grouping. 

For example, if I have a list of approved catering restaurants and grouped into cuisine types and I want the most popular ‘pizza’ group on top.  Rather than cuisine names Asian, Burgers, Cold cuts, Pasta, Pizza; I would use 01_Pizza, 02_Asian, 03_Cold cuts, 04_Pasta, 05_Burgers.

If you’ve done that, the next question your going to get from the customer is “Can we get rid of the leading number?” Yes, yes you can.

In your ContentQueryMain.xsl, add in this new template: OuterTemplate.RemovePrependedOrderDigits

    <xsl:template name=”OuterTemplate.RemovePrependedOrderDigits”>
        <xsl:param name=”GroupName”/>
        <xsl:choose>
            <xsl:when test=”contains($GroupName,’_')”>
                <xsl:variable name=”OrderBits”>
                    <xsl:value-of select=”substring-before($GroupName,’_')”/>
                </xsl:variable>
                <xsl:choose>
                    <xsl:when test=”translate($OrderBits,’0123456789′,”) = ””>
                        <xsl:value-of select=”substring-after($GroupName,’_')”/>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select=”$GroupName”/>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select=”$GroupName”/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

 

Then update the out of the box template, OuterTemplate.GetGroupName to call your new template.

<xsl:template name=”OuterTemplate.GetGroupName”>
        <xsl:param name=”GroupName”/>
        <xsl:param name=”GroupType”/>
        <xsl:choose>
            <xsl:when test=”string-length(normalize-space($GroupName)) = 0″>
                <xsl:value-of select=”$BlankGroup”/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:choose>
                    <xsl:when test=”$GroupType=’URL’”>
                        <xsl:variable name=”Url”>
                            <xsl:call-template name=”OuterTemplate.FormatValueIntoUrl”>
                                <xsl:with-param name=”Value” select=”$GroupName”/>
                            </xsl:call-template>
                        </xsl:variable>
                        <xsl:call-template name=”OuterTemplate.GetPageNameFromUrlRecursive”>
                            <xsl:with-param name=”Url” select=”$Url”/>
                        </xsl:call-template>
                    </xsl:when>
                    <xsl:otherwise>
                       <xsl:call-template name=”OuterTemplate.RemovePrependedOrderDigits”>
                            <xsl:with-param name=”GroupName” select=”$GroupName”/>
                        </xsl:call-template>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

Caveat: You’ll need to communicate that this numeric removal only takes place when groupings are prepended with a number and an underscore.

 

CQWP: 30Tips #6

If you’re customizing the .xsl styles for CQWP at all, you’ll pretty quickly typo a < or > or leave out a / somewhere.  When this happens, you won’t be getting any help from the inevitable error message.  Any and every CQWP that references your updated .xsl will suddenly be broken with out the slightest hint as to where the problem lies.  Thankfully the problem is almost always caused by invalid – not well formed – xml.

SharePoint Designer to the rescue.  In SPD 2010, you’ll find the Verify well-formed xml button on the edit tab when you are viewing .xml or .xsl files.  Clicking this button will do wonders for locating the missing character.

image

If you’re still working on a SharePoint 2007 farm or just working in SPD 2007 for some reason (there are reasons), you can do a ctrl+a select all and then right click to find the Verify well-formed xml option.

CQWP: 30 Tips #5

I mentioned before that the SP 2010 CQWP automatically creates the available slots by parsing your .xsl and creating a slot for all the @Variables it comes across.  When you dig into the item style though you may notice the presence of several @Variables in the out of the box templates that get no slot, such as @OpenInNewWindow

<a href=”{$SafeLinkUrl}” title=”{@LinkToolTip}”>
              <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>

If you scroll all the way down in ItemStyle.xsl, you’ll find the hidden template that does this:

<xsl:template name=”HiddenSlots” match=”Row[@Style='HiddenSlots']” mode=”itemstyle”>
    <div class=”SipAddress”>
      <xsl:value-of select=”@SipAddress” />
    </div>
    <div class=”LinkToolTip”>
      <xsl:value-of select=”@LinkToolTip” />
    </div>
    <div class=”OpenInNewWindow”>
      <xsl:value-of select=”@OpenInNewWindow” />
    </div>
    <div class=”OnClickForWebRendering”>
      <xsl:value-of select=”@OnClickForWebRendering” />
    </div>
  </xsl:template>

If you find that you want to make these available in your slots, which can be handy for LinkToolTip or OpenInNewWindow, you can simply remove them from the HiddenSlots template.

CQWP: 30 Tips #4

In the last tip, I told you that CQWP would populate several fields for you and I gave you an item template that would spit them out for you.  What I left out is that CQWP also populates a number of variables for you (variables are referenced with a $ instead of the @).  These variables are handed into your .xsl as parameters, not through the .xml.  Consequently, there is no easy itemstyle that will just enumerate them all.  Instead, you can see them all defined as parameters in the ContentQueryMain.xsl .

<xsl:param name=”cbq_isgrouping” />
    <xsl:param name=”cbq_columnwidth” />
    <xsl:param name=”Group” />
    <xsl:param name=”GroupType” />
    <xsl:param name=”cbq_iseditmode” />
    <xsl:param name=”cbq_viewemptytext” />
    <xsl:param name=”cbq_errortext” />
    <xsl:param name=”SiteId” />
    <xsl:param name=”WebUrl” />
    <xsl:param name=”PageId” />
    <xsl:param name=”WebPartId” />
    <xsl:param name=”FeedPageUrl” />
    <xsl:param name=”FeedEnabled” />
    <xsl:param name=”SiteUrl” />
    <xsl:param name=”BlankTitle” />
    <xsl:param name=”BlankGroup” />
    <xsl:param name=”UseCopyUtil” />
    <xsl:param name=”DataColumnTypes” />
    <xsl:param name=”ClientId” />
    <xsl:param name=”Source” />
    <xsl:param name=”RootSiteRef” />
    <xsl:param name=”CBQPageUrl” />
    <xsl:param name=”CBQPageUrlQueryStringForFilters” />
  <xsl:variable name=”BeginList” select=”string(‘&lt;ul class=&quot;dfwp-list&quot;&gt;’)” />
  <xsl:variable name=”EndList” select=”string(‘&lt;/ul&gt;’)” />
  <xsl:variable name=”BeginListItem” select=”string(‘&lt;li class=&quot;dfwp-item&quot;&gt;’)” />
  <xsl:variable name=”EndListItem” select=”string(‘&lt;/li&gt;’)” />

CQWP: 30 Tips #3

By default, CQWP retrieves quite a few fields.  These are fields that the web part sets for you. They don’t require any additional action by your user when the web part is added to the page.  The problem is they aren’t documented anywhere that I’ve ever come across.  Enter this trick from SP 2007’s CQWP:

Inside your ItemStyle.xsl, add this new template:

<xsl:template name=”FieldIdentifier” match=”Row[@Style='FieldIdentifier']” mode=”itemstyle”>
        <table>
            <tr>
                <td>——————–</td>
            </tr>
            <xsl:for-each select=”@*”>
                <tr>
                    <td>
                <xsl:value-of select=”name()” /> – <xsl:value-of select=”.” />
            </td>
                </tr>
            </xsl:for-each>
        </table>
    </xsl:template>

Then select FieldIdentifier in your CQWP as the item style.  For every record matching your query, it will spit out every available field in the xml.  The result is ugly, but extremely useful.

image

Did I mention it was ugly?  If you’re stuck in an SP 2007 environment (pre-SP2010’s Slots), you’ll use that template a lot.