So, let's imagine that you've built out a web site using Office SharePoint Server 2007. Your web pages, documents, and images are stored in SharePoint libraries. Content types define the schemas of discrete items, and sub-sites are used for organization and navigation. Now, the question is: how do I aggregate interesting slices of this information on places like my web site's home page?
Well, we have a great web part for doing just that right out of the box, and it's called the Content Query Web Part. This web part allows you to show items from your site based on a query, or set of rules, that you define. You can control what part of the site the web part looks for content, what types of items it returns, and it lets you filter, sort, and group those results. And, it lets you control how the items are rendered, so you can make these aggregations match the look and feel of the rest of your web site, both in what content is shown as well as how it's styled.
The best way to show what the web part is capable of is to walk through an example. Let's say that you've defined a type of page in your site called a "Product Page". A Product Page has a set of common fields, like Title, Description, and Body, but it also has some additional metadata that tells you what product line the page is for. Now, let's say that you want your home page to feature a list of the latest 5 product pages from your entire site that are about the Widget product line. Furthermore, you want to show this list of product pages by displaying the Title of the page as well as a portion of the Body content, with a little "more..." link that takes people to the full article. Something like:
Widget 2007The Widget 2007 Beta 2 has recently gone to market. This innovative... (more)
Widget Community launches!Our first community driven application portal has just launched. You can...(more)
OK, let's get to work!
Step 1: add a Content Query Web Part to the home page
This part is pretty basic. I go to the home page of our site, click on Site Actions, and click Edit Page. The page is checked out to me, and is placed in edit mode. In one of the web part zones, I click "Add Web Part", scroll down to the Content Query Web Part, select it, and add it.
Now, I have a Content Query Web Part on my checked-out version of the home page. It's running a default query that shows me all of the web pages in my site collection.
Step 2: configure Content Query to rollup product pages
Well, that's an OK query as a placeholder to show me that the web part is working correctly, but the results are not exactly what I want to show. So, I have to edit the web part and configure it to show product pages. First, I click on the web part menu and select Modify Shared Web Part.
The toolpane opens and I see sections of properties. The Query section lets me configure what content the web part will show, and the Presentation lets me configure how the content is displayed.
Let's expand the Query section and configure this part:
Now, if I click Apply on my web part, I see just product pages appearing!
OK, but my tasks is to show the latest 5 product pages that are about the Widget product line. Let's look further down the toolpane UI and see what we can do.
Now, if I click Apply on my web part, I see not only just product pages, but the latest 5 product pages about the Widget product line!
OK, we're getting close. But...hmm, the styles don't look quite right. I see a title, but I don't see the body text and the "more...". How do we fix that?
Step 3: customize Content Query to ask for additional product page fields
Anytime you want the Content Query web part to show specific fields from the items that you're aggregating, you have to do two things:
Let's tackle the first one. So, I want to have the web part show the Body field from the product pages, so I have to configure the web part to ask for it.
First, I export the web part that we've added. From the web part menu, I select Export..., and pull down the .webpart file. This is just a text file that shows all of the properties of the web part and their values.
We look for the property called "CommonViewFields". This property makes the web part request additional fields, on top of the "base" ones it asks for out of the box. We can edit this property and specify one additional field to ask for, namely the Body field.
<property name="CommonViewFields" type="string">Body_x0020_content, RichHTML</property>
There's a few ways you can configure this property but the most common one is "Internal name of field", followed by a comma, followed by the type of the field. If you want more than one, add a semicolon between each pair. (Don't worry, we have an SDK article coming soon that gets into all the details of using this and other properties.)
Now, all we have to do is save this .webpart file and import it back on the site. By selecting Import from the toolpane, and browsing to the .webpart file, you can upload this new .webpart and then add it to your page.
As soon as we add our web part, we see...
Wow, that looks exactly the same! Right, so the web part now has the Body field content, but it's not rendering the content. How do I make the web part do that?
Step 4: customize XSLT to render additional fields
The Content Query web part utilizes XSLT to render its contents. This means that I can edit the way the web part renders content and configure exactly what is shown and how it's shown.
If I edit the web part and look at the toolpane, I'll see a couple of drop-downs that relate to Styles. These correspond to the Header and ItemStyle XSLT files that are located in the site collection's Style Library, which is in the root site.
I see that the web part is currently configured to use the "Image on left" style. If we open the ItemStyle file, we'll see several xsl templates. Each corresponds to an item style in the drop-down above. The Image on left style looks like this:
<xsl:template name="Default" match="*" 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> <xsl:variable name="LinkTarget"> <xsl:if test="@OpenInNewWindow = 'True'" >_blank</xsl:if> </xsl:variable>
<div id="linkitem" class="item"> <xsl:if test="string-length($SafeImageUrl) != 0"> <div class="image-area-left"> <a href="{$SafeLinkUrl}" mce_href="{$SafeLinkUrl}" target="{$LinkTarget}"> <img class="image" src="{$SafeImageUrl}" mce_src="{$SafeImageUrl}" alt="{@ImageUrlAltText}" /> </a> </div> </xsl:if> <div class="link-item"> <xsl:call-template name="OuterTemplate.CallPresenceStatusIconTemplate"/> <a href="{$SafeLinkUrl}" mce_href="{$SafeLinkUrl}" target="{$LinkTarget}" title="{@LinkToolTip}"> <xsl:value-of select="$DisplayTitle"/> </a> <div class="description"> <xsl:value-of select="@Description" /> </div> </div> </div> </xsl:template>
The style breaks down into two sections:
We see that this style renders an image, a title, and a description. For the scenario above, all I have to do is change that description line:
<div class="description"> <xsl:value-of select="@Description" /> </div>
and make it show the Body content field:
<div class="description"> <xsl:value-of select="@Body_x005F_x0020_content" /> </div>
If I save the XSLT and reload the page with my web part, I see:
Great, I'm finally done!
Tips and tricks
<xsl:for-each select="@*"> P:<xsl:value-of select="name()" /> </xsl:for-each>
I hope this walkthrough helps people configure and use the Content Query Web Part. I'd be interested to hear and see examples of how people are using the web part, as well as field questions. So, post your comments!
--George Perantatos, Program Manager