Using Dynamic Filtering with the CQWP – PageQueryString Value
One of the really cool features of the Content Query Web Part (CQWP) is the ability to do dynamic filtering.
-
The two options for dynamic filtering include:
-
PageFieldValue
- Token allows specify field on page layout and dynamically replaces value of filter with current page’s field value
-
PageQueryString
- Use URL query string for a value to use in Query
-
In this post, I will demonstrate how to work with the PageQueryString value and then in a part two blog post I will demonstrate how to work with the PageFieldValue. As a speaker of tech conferences, I will use speakers as my demo content and base it off a custom list. The solution I am providing is something I have implemented for various types of content for customers.
Jacksonville University Example
A real world example of using the CQWP with dynamic filtering would be what I implemented for Jacksonville University’s public facing website (www.ju.edu).
The screenshot below is a partial screenshot of the Employment Opportunities publishing page. The page has a CQWP that is configured to pull the job opps from custom lists and uses custom XSL templates to render the items and provide the link to each item which includes the query string parameter in the URL.
The next screenshot is the Opportunity Details page that has a single CQWP configured to use my custom template and is filtered based on the PageQueryString value. The parameter used is JobID which is populated with the list item’s ID.
http://www.ju.edu/humanresources/Pages/AdminOppDetails.aspx?JobID=112
Implementation
This solution will work in both O365 and on-prem. For this demo, I am using an O365 Team Site that has the publishing features activated and contains 4 subsites (Australia/New Zealand, Canada, Europe/UK, & US). I created a Speaker content type, site columns, created a list template, and then created a speakers list in each of my subsites as detailed in Using Custom Content Types with Lists.
The Global home page will rollup all the speakers from the subsites and each subsite’s home page displays the speakers based on the subsite.
XSL Style Sheet Templates
I created two different XSL style sheet templates in my DemoItemStyle.xsl file. To learn more about using the CQWP with custom XSL style sheets please see Content Query Web Part – Part One: Using Custom XSL Style Sheets.
Speaker Rollup Pages
On the home page of the site and the home page of all the subsites, I added a CQWP and configured it to use my SpeakerRollup XSL style sheet template. I took a copy of the existing default (Image left) template and modified it removing what I didn’t want and added new markup.
Line 3: has the variable speakerUrl which is linking to my SpeakerBio.aspx page.
Line 41 & Line 53: build the href to the page appending the querystring value Speaker to equal the speakername variable ?Speaker={$speakername}
<xsl:template name="SpeakerRollup" match="Row[@Style='SpeakerRollup']" mode="itemstyle"> <xsl:variable name="speakername" select="@Title" /> <xsl:variable name="speakerUrl" select="'/sites/demo/Pages/SpeakerBio.aspx'" /> <xsl:variable name="SafeImageUrl"> <xsl:call-template name="OuterTemplate.GetSafeStaticUrl"> <xsl:with-param name="UrlColumnName" select="'ImageUrl'"/> </xsl:call-template> </xsl:variable> <div class="speaker-wrapper"> <div class="speaker-image item"> <xsl:if test="string-length($SafeImageUrl) != 0"> <div class="image-area-top"> <a href="{$speakerUrl}?Speaker={$speakername}"> <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> <img class="image" src="{$SafeImageUrl}" title="{@ImageUrlAltText}"> <xsl:if test="$ImageWidth != ''"> <xsl:attribute name="width"> <xsl:value-of select="$ImageWidth" /> </xsl:attribute> </xsl:if> <xsl:if test="$ImageHeight != ''"> <xsl:attribute name="height"> <xsl:value-of select="$ImageHeight" /> </xsl:attribute> </xsl:if> </img> </a> </div> </xsl:if> <div class="speaker-rollup"> <xsl:call-template name="OuterTemplate.CallPresenceStatusIconTemplate"/> <a href="{$speakerUrl}?Speaker={$speakername}"> <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> </a> <a href="{$speakerUrl}?Speaker={$speakername}"> <div class="speaker-link"><xsl:value-of select="$speakername"/></div> </a> </div> </div> </div> </xsl:template>
Global Home Page CQWP Configuration
Subsite Home Page CQWP Configurations
For the subsite home pages, I used the same settings as the Global except the following.
Speaker Bio Page
The Speaker Bio page (SpeakerBio.aspx) is a publishing page that I created at the root site collection and added a CQWP on the page. I created an XSL style sheet template called SpeakerBio and configured the CQWP to use this template and and filter based on the PageQueryString value.
When I click on a speaker, the URL will contain the querystring value for other speaker. For example, if I click on Wictor his URL would be the following:
https://spglobal.sharepoint.com/sites/demo/Pages/SpeakerBio.aspx?Speaker=Wictor Wilen
XSL style sheet template (SpeakerBio)
<xsl:template name="SpeakerBio" match="Row[@Style='SpeakerBio']" mode="itemstyle"> <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="speakerblogsite" select="@BlogSite" /> <xsl:variable name="speakerlinkedin" select="@LinkedIn" /> <xsl:variable name="speakertwitter" select="@Twitter" /> <xsl:variable name="speakername" select="@Title" /> <div class="speakerbiowrapper"> <div class="speakerbio-image image-area-left"> <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> <img class="image" src="{$SafeImageUrl}" title="{$speakername}"> <xsl:if test="$ImageWidth != ''"> <xsl:attribute name="width"> <xsl:value-of select="$ImageWidth" /> </xsl:attribute> </xsl:if> <xsl:if test="$ImageHeight != ''"> <xsl:attribute name="height"> <xsl:value-of select="$ImageHeight" /> </xsl:attribute> </xsl:if> </img> </div> <div class="speaker-name"> <xsl:value-of select="$speakername" /> <xsl:if test="@MVP = 'True'"> <span class="speaker-mvp"> <img src="/sites/demo/SiteAssets/Images/mvp.jpg" /> </span> </xsl:if> </div> <div class="speaker-bio"> <xsl:value-of select="@SpeakerBio" disable-output-escaping="yes" /> </div> <div class="speaker-social"> <xsl:if test="$speakerblogsite != ''"> <div class="speaker-blog"> <b>Blog:</b><xsl:text> </xsl:text> <a href="{$speakerblogsite}"><xsl:value-of select="substring-after($speakerblogsite,',')"/></a> </div> </xsl:if> <xsl:if test="$speakerlinkedin != ''"> <div class="speaker-linkedin"> <b>LinkedIn:</b><xsl:text> </xsl:text> <a href="http://www.linkedin.com/in/{$speakerlinkedin}"><xsl:value-of select="$speakerlinkedin" /></a> </div> </xsl:if> <xsl:if test="$speakertwitter != ''"> <div class="speaker-twitter"> <b>Twitter:</b><xsl:text> </xsl:text> <a href="http://www.twitter.com/{$speakertwitter}"><xsl:text>@</xsl:text><xsl:value-of select="$speakertwitter" /></a> </div> </xsl:if> </div> </div> </xsl:template>
https://spglobal.sharepoint.com/sites/demo/Pages/SpeakerBio.aspx?Speaker=Christina Wheeler
Speaker Bio Page CQWP Configuration
The PageQueryString value is set on the Additional Filters options and since the URL string built in the SpeakerBio XSL style sheet template is ?Speaker the value set in the web part is [PageQueryString: Speaker].
Custom Styling
To display the rollup of speakers in columns I added custom CSS to the site.
div.speaker-wrapper { float:left; display:block; } .speaker-rollup, .speaker-image { text-align:center; border:0px red solid; width:300px; } .speaker-link { text-align:center; color:#0072c6; font-size: 14px; padding-bottom:15px; } a:visited { color:#0072c6; } .speaker-name { font-weight:bold; font-size:20px; padding-bottom:10px; } .speaker-bio { width:60%; font-size:14px; } .speakerbio-image { margin-right:15px; margin-bottom:5px; } .speaker-mvp { padding-left:10px; } .speaker-social { padding-top:10px; } .speaker-blog, .speaker-linkedin, .speaker-twitter { padding-top:10px; }