Client Side Rendering (JSLink) with Content by Query Web Parts

Applies to SharePoint 2013, 2016


Standard Client Side Rendering (CSR) cannot be applied to Content by Query web parts (CQWP). However, using the open source csrShim stylesheet, CQWPs can also utilize JavaScript based rendering.

Content by Query Web Parts were heavily utilized in earlier versions of SharePoint but have fallen out of favor due to their complexity and limitations. However, they have proven to be performant options (in on premises deployments) that can continue to solve a variety of problems.

When used in appropriate situations, CQWPs can be very powerful assets. Unfortunately, the Out Of The Box (OOTB) limitation against CSR has made it inaccessible to newer developers. However, csrShim enables CSR for CQWPs using OOTB configurations and rendering tools.

This is not a comprehensive guide to using CQWPs or csrShim but provides the tools needed to bridge the gaps and enable CSR. For additional details about how to use csrShim see the csrShim Documentation on GitHub.

How to Get the Code

The example created using the steps in this document can be found in full as part of the csrShim repository:

The full project can be found on GitHub:

You can download or clone the repository directly from that site. You can also view the code directly on the site.


Content by Query Web Parts

The Content by Query Web Part (CQWP), often just called the Content Query Web Part is part of SharePoint’s Enterprise Content Management (ECM) toolset. CQWPs aggregate list items across a site hierarchy while providing query optimization and caching.


  • Aggregation of list items across a single site collection
    • Can aggregate items from a single list, multiple lists by list type or contenttype, and more
  • Basic queries can be configured using OOTB web part tool pane
  • Respects Audiences
  • Powerful caching leading to high performance in on-premises deployments
  • Is not subject to search’s limitations (use of managed properties, crawl delay, search language, etc.)
  • OOTB display templates


  • Cannot cross site collections
  • Advanced configuration can be difficult
  • Custom display requires complicated XSL (unless using csrShim)
  • Caching benefits are nullified when used in Office 365 leading to poor performance
  • Does not have some of search’s benefits (pre-aggregated results, cross site collection, extreme scalability, etc.)
  • Some fields (such as user fields) do not return as much detail as list view web parts

When to Use

You can use the CQWP when:

  • You are using Audiences with list items
    • Standard list views and APIs do NOT support audience filtering
  • You are aggregating across lists/contenttypes and the search crawl delay is unacceptable (or the configuring of search schema is prohibited)

Don’t use the CQWP when:

  • You need to cross site collections
  • Targeting Office 365
  • Search can be used instead

Standard Client Side Rendering

Client Side Rendering (CSR), often referred to as JSLink, is a technology introduced with SharePoint 2013 that provides extension points to use JavaScript to render SharePoint data. CSR continues to be supported in SharePoint 2016 and Office 365.

Additional information about how to use standard client side rendering with list views can be found in my earlier List View Client Side Rendering (JSLink) Primer series.

SharePoint does not support using standard CSR with CQWPs (No JS Link property is defined). However, csrShim exposes a parameter that will enable this functionality including the same set of event callbacks and templates described in the above guide.


csrShim is an open source solution that fills the gap of many of the limitations presented by the OOTB client side rendering.

csrShim is an XSLT solution that can be used to:

csrShim is available through GitHub at:

Getting Started

In the following examples, we will be targeting on premise SharePoint 2013 using SharePoint Designer 2013. We will be using a publishing site to have access to the Content by Query web part.

Additionally, we will be using the same list from the List View Client Side Rendering (JSLink) Primer series (with the exception that the Person field has a different Show field property). The CSR JavaScript file has also been adapted from the HallOfFame.js file created with that guide. Thus, many of the details around how CSR works are left out of this post. However, if you are already familiar with CSR basics you shouldn’t have any trouble following along.

The goal of this post, and this example, is not how CSR works but only how to use it with CQWPs.

List Setup

For this example, we will be using a custom list with just 3 columns:

  • Title (Text)
  • Person (User)
  • Color (Choice)

A HallOfFame.xml PnP template with this list is available if you are familiar with how to apply PnP provisioning templates.

Otherwise, to manually create the list:

  1. From a site where you have full control or design permissions, using the Site Actions menu (gear) choose Add an App
  2. Choose Custom List
  3. Name the list Hall of Fame and click Create
  4. From Site Contents, hover over the Hall of Fame icon and click the ellipsis to show the panel and choose Settings:
  5. Under Columns, click Create column
  6. Give a name of Person and set the type to Person or Group and set the Show field to Account then click OK:
  7. Under Columns, click Create column again
  8. Give a name of Color and set the type to Choice (menu to choose from). Replace the choices with Tomato, YellowGreen, DeepSkyBlue, Gold (each on separate lines):
  9. Navigate to the Hall of Fame list and add several entries:

You now have a basic list and you could simply use standard CSR to display the contents if that’s all you wanted. For this example, we will only have the one list since our goal is to demonstrate how to use the CQWP with csrShim.

Generally, however, you might have multiple copies of this list across several subsites and you would use a CQWP to roll all the results up to a single view. In this scenario, standard CSR would be unavailable to you and is exactly where csrShim fills that gap.

Also, note that we specifically set the Person Field’s Show field property to Account. Unlike with list views, CQWPs get very little information from user fields. Most of the Show field options will return the user’s name (and nothing else). List views return many properties including ID, account, email, etc. So, we must choose carefully so that we retrieve additional information if needed (in this case the profile picture).

Script Setup

We will be using a modified version of the JSLink file created with the List View Client Side Rendering (JSLink) Primer series. This script is available at the sample code location mentioned in the introduction (HallOfFame.js).

A full description of each of the templates/functions was provided in the primer series and should be consulted for any questions. The primary differences between that version and this one are:

  • The BaseViewID has been set to 40
    • This isn’t strictly necessary but is recommended when using csrShim so that you know your JSLink is very specifically targeted and can therefore be hosted alongside standard CSR and other csrShim implementations without conflict
  • The Item template was modified
    • Since the CQWP doesn’t return a full user object, we can’t simply get the profile picture from the Person field. So, the photo is always set to the placeholder image and has its visibility set to hidden
    • The user URL is also not set since we don’t have a user ID
  • The PostRender callback was modified
    • Code has been added to retrieve the PictureUrl and UserUrl from the User Profiles for each of the users based on their account name. Once those properties have been retrieved, the placeholder image is replaced (where appropriate) and visibility is set to visible. The href for the link is also set to the retrieved UserUrl.

Upload the HallOfFame.js file to a library within your site (The Style Library of the root site of a site collection is a great spot!).

csrShim Setup

To use csrShim, a CQWP only needs 2 files:

Place these in a library within your site (The Style Library of the root site of a site collection is great spot for these!).

Configuring a CQWP to use csrShim

Adding a CQWP to a Page

On a web part page where you want to display your CQWP:

  1. Edit the page
  2. Click the Add a Web Part button in the zone where you wish your CQWP to end up
  3. Choose Content Query under Content Rollup (if you don’t have this option then the publishing features are not enabled)
  4. Using the web part dropdown, choose Edit Web Part to open the toolpane
  5. Expand the Query section and select Show items from the following list then click Browse and locate the Hall Of Fame list created earlier:
  6. Again, this is a simple example (generally a single list CQWP view is not a great use case for a CQWP). However, any query that returns results with the CQWP (even complicated ones) can still take advantage of CSR display using csrShim.
  7. Click OK and choose to Stop Editing the page

You now have results on the page but only the Title field is showing and there is no custom display at all.

CQWP Configuration

Basic queries and sorting can be applied using the toolpane. However, you are fairly limited in how these results are displayed (including which fields are returned) and even in how complicated you can make your filters (query).

For all but the most basic CQWPs, you’ll likely end up manually editing the CQWP configuration either through SharePoint Designer or by exporting the definition, making your edits, and reimporting.

Since we used a web part page, we will simply use SharePoint Designer (SPD) to edit the configuration of the part directly. Other types of pages cannot always be edited in SharePoint Designer. In which case, you must apply the following changes into an exported web part definition file (XML). These changes are the same, but end up looking different from this example (You use property elements rather than setting the properties directly).

The easiest way to overcome this limitation is to use a web part page temporarily until your web part is properly configured using the below methods. Then export the web part from there and import into your other page types.

To edit the web part in SharePoint Designer:

  1. Connect to your site in SharePoint Designer
  2. In the navigation pane choose the library where you stored your page (if not listed, use the All Files node)
  3. Right-click on your page and choose Edit File in Advanced Mode
  4. SharePoint Designer often “helpfully” changes things that can cause problems. For instance, it is very common that it will escape double quotes within existing script blocks that should not be escaped. This will throw errors on your page.
  5. Look for the following:
    <SharePoint:ScriptBlock runat="server">
    var navBarHelpOverrideKey = &quot;WSSEndUser&quot;;
  1. You will need to replace the values with actual double quotes (Again, this has nothing to do with this solution, this is just a common problem with SPD that may come up repeatedly):
    <SharePoint:ScriptBlock runat="server">
    var navBarHelpOverrideKey = “WSSEndUser”;
  1. Look for the following:
    <SharePoint:ScriptBlock runat="server">
    if(typeof(MSOLayout_MakeInvisibleIfEmpty) == &quot;function&quot;)
  1. Again, you will need to replace the values with actual double quotes:
    <SharePoint:ScriptBlock runat="server">
    if(typeof(MSOLayout_MakeInvisibleIfEmpty) == “function”)
  1. Go ahead and save the page. In the Site Definition Page Warning dialog, click Yes:

Using csrShim

To use csrShim, you need to tell the CQWP to use the csrShim stylesheet. The CQWP uses 3 stylesheets (Main, Item, and Header). Unlike most web parts with a single XslLink property, the CQWP has one for each.

We will only use the Main, but you must provide a link for the Item and Header values or your web part will get an error. That is where the EmptyStyleSheet included with csrShim comes in handy.

  1. Add the MainXslLink property directly to the ContentByQueryWebPart element on your page and give it the address of the xsl stylesheet
  2. Add the HeaderXslLink property directly to the ContentByQueryWebPart element on your page and give it the address of the xsl stylesheet
  3. Add the ItemXslLink property directly to the ContentByQueryWebPart element on your page and give it the address of the xsl stylesheet
  4. Save the page in SPD and refresh it in the browser. You should now see many more fields in a strange display (this is the OOTB template-less CSR view)

Adjusting the Query

Now we’re getting somewhere! Clearly, this isn’t the display we’re going for just yet but csrShim is in place and ready to have a JS Link file applied.

First, however, it’s a good idea to get your query adjusted before introducing the complication of custom rendering. Often, you’ll accomplish this by using the QueryOverride attribute with your own CAML. For this example, we want to return all the items but we want it sorted in order of creation, ascending. For simple sort changes, we’ll just use existing properties (we could have done this in the toolpane as well).

  1. By default, the SortBy attribute should already be set to Created. The SortByDirection is set to Desc by default. Change this to Asc and Save the page in SPD.

Additional Fields

If you look through the many fields that are returning on the page, you’ll notice that the Person and Color fields are missing. You can request additional fields using the CommonViewFields property:

  1. Add the CommonViewFields property directly to the ContentByQueryWebPart element on your page and give it the value of Title,Text;Person,User;Color,Text;
  2. Save the page in SPD

Refreshing the page in the browser will show that the values for these columns are now showing up, yay!

A Note about Field Types

Although there is a Choice option for the type (the text following the comma after the internal name), Text always works and Choice only sometimes. In the sample’s case, either is fine, but a multi-choice column will cause your CQWP to not return any data if Choice is used but will work fine with Text. Therefore, it is recommended to always use Text for Choice columns.

Other types that can be used:

  • Text
  • Note
  • Number
  • Currency
  • Integer
  • Boolean
  • DateTime
  • Threading
  • Lookup
  • Choice
  • URL
  • Counter
  • DisplayOnly
  • RichHTML
  • Image

Applying Client Side Rendering

Technically, we’ve already applied client side rendering simply by using csrShim as the stylesheet. If you check using your development tools, you’ll find a ContextInfo object in the global namespace (likely ctx500).


Now to apply our JS Link file to the CQWP!

With list views, you can simply open the toolpane and put your script reference(s) in the JS Link property of the XSLTListView web part. There is no JS Link property on the CQWP. Instead, csrShim exposes several parameters including a JSLink parameter where we can specify these. This is done through the CQWPs ParameterBindings element.

  1. Add a ParameterBindings Add a ParameterBinding element with a Name of BaseViewID and a Default value of 40. Add another ParameterBinding element with a Name attribute of JSLink and a Default value of the address to the HallOfFame.js file we uploaded earlier.

      <ParameterBinding Name="BaseViewID" Default="40"/>
      <ParameterBinding Name="JSLink" Default="/Intranet/Style Library/csrShim/HallOfFame.js"/>

If you refresh the page, you’ll see the glory that is CSR with a CQWP!


Best Practices for csrShim with CQWPs

  • Set the XslLink for ALL 3 CQWP properties
    • MainXslLink = address of csrShim.xsl
    • ItemXslLink = address of EmptyStyleSheet.xsl
    • HeaderXslLink = address of EmptyStyleSheet.xsl
  • Use the CommonViewFields property of the CQWP to include additional fields
  • Use Text for Choice fields in the type portion of the CommonViewFields property
  • If fields are coming back as GUIDs instead of their internal name, use the DataMappings property of the CQWP
  • Provide a unique BaseViewID to prevent conflicts with the default value of 1 (standard CSR with list views uses this value)
  • If reusing JSLink files between CQWPs, list views, and/or feeds, use the ctx.ShimType property to create conditional property retrieval as needed

Changing Web Part Properties When the Page is Unavailable

Applies To: SharePoint

The other day we made some changes that caused some issues with how one of our web parts was configured. Unfortunately, I hadn’t wrapped the problem in a try/catch and my error blew up the whole page. I’m sure I’m the only one that’s ever done that. So obviously I’ve got some code changes to make, but what do I do in the meantime? Fortunately, there’s some straight forward Powershell that lets you change web part settings (even custom properties like mine).

I found the solution to this over on where he was using the technique to change a web part that automatically redirected the user. I’ve just reproduced his code here and added some explanation and background.

When I first went to solve this problem I tried the ?contents=1 querystring trick to pull up the Web Part Administration page. If you’re looking for a quick solution you can add that query string to the end of your page’s URL and then delete the web part from the page and start over. But a more elegant solution is to just change the offending property using some easy Powershell.

Using the SharePoint 2010 Management Shell, run the following commands:

$web = Get-SPWeb ""
$page = $web.GetFile("default.aspx")
$wpm = $web.GetLimitedWebPartManager("default.aspx",[System.Web.UI.WebControls.WebParts.PersonalizationScope]::Shared)
$part = $wpm.WebParts[0]
$part.SomeProperty = "The correct setting!"
$page.CheckIn("Fixed that property")
$page.Publish("Fixed that property")

What Just Happened?

In line 1 we’re just getting a reference to the web site (SPWeb) where your web part lives using Get-SPWeb. Just replace the URL shown with yours.

Lines 2-3 and 8-9 are only required if the page you’re modifying is on a publishing site or check in/out is required. Feel free to skip these (go directly to line 4) if you’re just editing a simple page. If your page does require check out to be edited, line 2 is simply retrieving the file (SPFile) using the GetFile method using the relative location of the page. Then line 3 calls the CheckOut method which, of course, checks out the file.

In line 4, we’re grabbing a reference to the Web Part Manager for the page (SPLimitedWebPartManager) using the GetLimitedWebPartManager method. Just replace the first parameter with the relative location of your page. The second parameter is the PersonalizationScope enumeration and can be User or Shared. You’re going to want to use Shared to affect everybody. The Web Part Manager object is what lets us get access to all the web parts on the page and screw with em.

In line 5, we grab the web part (WebPart) we want by index using the WebParts collection. In the example above I already knew that the web part I wanted was the first one in the collection. You can also pass the uniqueID property of the web part (instead of the index). You can find out both by simply calling the WebParts collection by itself ($web.WebParts) and everything will get listed to the screen.

To see all the available properties of the web part you can just type ($part) and it will list everything out including any custom properties. Then you can just set them like we do in line 6.

Line 7 uses the Web Part Manager’s SaveChanges method to incorporate all your changes. Lines 8-9 are again only required if your pages library requires check in/out and publishing. If it’s a simple page just skip to line 10. Line 8 uses the CheckIn method which takes a string for a check-in comment. Line 9 uses the Publish method which also takes a string for a comment.

Line 11 just calls the Close method and ensures we clean up all our resources.

That’s it! Now you can wrap that up in a script to loop through multiple pages and change properties on all sorts of web parts or just one-off fix those web parts you might have broken.

Refinement Panel Customization Saving Woes

Applies To: SharePoint 2010

Editing the Filter Category Definition of a Refinement Panel web part can make your search result pages so much better. This is one of the first things we customize and every time we do, I get tripped up by a really annoying setting in the web part.

Problem Scenario

I replace the XML in the Filter Category Definition property in the Refinement properties section of the web part. I hit Apply and everything validates. I save the page and run the results – No custom refinements! In fact, when I open the web part back up for editing, my custom Filter Category Definition is totally wiped out! Why isn’t it saving!?!?!?! Why am I weeping ever so softly?!?!! Why would I confess that on the internets?!?!?!?!


There’s a checkbox at the bottom of the Refinement properties section labeled, Use Default Configuration. This is checked by default. Unless you uncheck this when you place your custom XML in the property, it is going to completely ignore you and replace it with the default XML.


I can see why things work this way, but it is extremely unintuitive. It would seem that the web part should recognize there is custom XML in the Filter Category Definition and understand that’s what it should use. Then a button (NOT a checkbox) that says something along the lines of “Revert to Default Configuration” would be used to reset that XML when needed.

Oh well, nobody is asking my opinion anyway. So do yourself a favor and remember to uncheck that box whenever customizing the Filter Category Definition.

Broken Add New Document Links

Applies To: SharePoint 2010

We ran into an interesting problem the other day where a user called and said that everytime they clicked the Add New Document link they got a giant error message. I went to the site and was able to confirm that it was indeed blowing up.

This was only happening when the document library was being exposed through a web part on another page. Going directly to the library and clicking New Document or Upload Document in the ribbon worked just fine. The problem was obviously with the web part toolbar, which in this case was set to Summary Toolbar.

It appears this is something left over from our upgrade from SharePoint 2007 to SharePoint 2010. I would’ve thought the Visual Upgrade would have fixed this and it’s amazing no one noticed for well over a year! It seems that Microsoft changed not only the look of the link (switching the icon from a little square to a green plus and removing the word new) the underlying address also changed.

Broken Old Style Link
Correct Style Link

Taking a look at where these links were pointed, I could see that the old style link was pointed at listform.aspx:


While the new style link was pointed at Upload.aspx:


Fixing this is pretty easy. Just edit the web part and change the Toolbar Type to No Toolbar and click Apply:


Then immediately switch the Toolbar Type back to Summary Toolbar and press OK:


Interestingly, other web parts sometimes show the old style link too (links, announcements, etc.) but since these all seem to still use the listform.aspx they continue to work. However, you can use the above technique to get them to match visually as well (green plus icon).

Hiding the List Item Selection Boxes

Applies to: SharePoint 2010

In SharePoint 2010 the standard listviewwebpart adds a checkbox to the left of each row. These only show up on hover and when you check the box the entire row is highlighted. You can check multiple boxes (or even use the helpful checkbox up top to select/unselect them all at once). This allows you to perform the same action on the selected item(s) using the ribbon.

SelectionBox MultiSelection

Generally, this is a good feature. However, not everybody agrees. If you’re doing some customization and you don’t want them to show up, you can do it through CSS. Although this is the technique I previously used, I ran across a post by Glyn Clough that made me face palm. I’ll leave the CSS technique in case it helps somebody and since I can think of at least one or two reasons you might want it (simple removal of all select boxes across an entire site or keeping the selection logic without the boxes) but if you want the simple answer just skip right to that solution.


If you’re deploying a branding solution or already using a custom style sheet just add the following:

.s4-itm-hover .s4-itm-cbx,
.ms-itmhover:hover .s4-itm-cbx,
.s4-itm-selected .s4-itm-cbx,
.ms-inlineEditLink .s4-itm-inlineedit,
.ms-itmhover:hover .s4-itm-inlineedit,
.s4-itm-hover .s4-itm-inlineedit,
.s4-itm-selected .s4-itm-inlineedit
    position: relative;
    top: 0;

Bam! no more selection boxes! However, I’ve got no clue why you would want to hide those for an entire site. More likely you want to hide these from a specific list view or page. To do this you can slap a content editor web part on the page(Edit Page, Add a Web Part, Media and Content > Content Editor) and click inside it. Then choose the HTML drop down and pick Edit HTML Source:


Then paste this inside there:

.s4-itm-hover .s4-itm-cbx,
.ms-itmhover:hover .s4-itm-cbx,
.s4-itm-selected .s4-itm-cbx,
.ms-inlineEditLink .s4-itm-inlineedit,
.ms-itmhover:hover .s4-itm-inlineedit,
.s4-itm-hover .s4-itm-inlineedit,
.s4-itm-selected .s4-itm-inlineedit {
    position: relative;
    top: 0;

Save the page and you should see that all the list views on the page no longer have the selection box (although you can still click on the item(s) and get selection and multiselection):

NoSelectionBox MultiSelectionNoBox

So what about that Select All box up there? Why you want to break all the interfaces!?!

Unfortunately this isn’t as straight-forward. Microsoft did provide a convenient class for the checkbox: s4-selectAllCbx. However, until you hover over the web part, that class is not applied to the input control – Very strange. So applying some styles to that class will only take effect after someone has hovered over the part.

If you really want to do this with CSS you can add an additional selector to the above styles to get this (the key is that last selector .ms-vh-icon input):

.s4-itm-hover .s4-itm-cbx,
.ms-itmhover:hover .s4-itm-cbx,
.s4-itm-selected .s4-itm-cbx,
.ms-inlineEditLink .s4-itm-inlineedit,
.ms-itmhover:hover .s4-itm-inlineedit,
.s4-itm-hover .s4-itm-inlineedit,
.s4-itm-selected .s4-itm-inlineedit,
.ms-vh-icon input {
    position: relative;
    top: 0;

This hides them all but doesn’t shrink the column. There’s probably a CSS way to do that too, but honestly let’s just use the setting below.

The Real Solution

So everything above has been overkill. I remember looking for a simple setting to turn those boxes off and not finding it. I can’t be the only one since you’re reading this article – but it doesn’t get much easier than this.

Just edit the view (either the view used by the web part or an actual view on the list) and scroll down to the Tabular View section and uncheck the box next to Allow individual item checkboxes:


Click OK and now those checkboxes are removed! Unfortunately so is all selection and multi-selection. So if you have some strange need to keep the selection but remove the boxes, see the CSS solution above. If you just wanted to remove them altogether, remember to always look at the settings!

If you take a look at the XML generated for the view you’ll see that all this is doing is adding a TabularView attribute to your View element and setting it to FALSE.

InfoPath List Form New Item is Read Only

Applies To: SharePoint 2010, InfoPath 2010

Many of you are probably aware that you can replace the standard list item forms with InfoPath browser based forms (SharePoint 2010 Server Enterprise only), and if you weren’t, you are now. It’s as simple as hitting the Customize Form button on the List tab of the List Tools ribbon:

By default the same form is used for all three views (New, Edit, & Display). You can create new views in InfoPath (Page Design tab -> New View) and then back in SharePoint use the Form Web Parts dropdown shown above to customize the InfoPath Form Web Part to show the view you want. There are other guides out there to getting this done that go into more detail, but that’s the gist of it.

I ran into an interesting problem the other day when using this feature. I had a form view for New, Edit & Display and everything was working great. Then I realized that I had some optional fields that I didn’t want to show on the display form if they were blank.

So I wrapped those up in a section and slapped a formatting rule to “Hide this control”:

Boom! I published the form and everything displayed as expected. I did a bunch of other stuff and then went back to add another item to the list. Suddenly the form view I was using for the New List Item was completely Read-only. Obviously, that’s a problem.

I opened the form back up in InfoPath and made sure the View Properties didn’t have the Read-only checkbox checked – Nope. I cried a little but then through the blur of my tears I noticed that every field on every view that wasn’t in one of my auto hide sections had a little blue info icon. Hovering over the icon showed FieldName (Control bound to missing field or group). What a heck?

Meanwhile the Edit form is still working great. So I right-clicked on the fields choose Change Binding and verified they were all hooked up correctly. Some searching brought me to this TechNet thread. The answer is in there but it wasn’t super obvious to me.

Basically, by adding the sections I had caused all the other fields on all the views to be outside the SharePointListItems_RW section and this breaks their binding. So how do you fix it? It’s actually pretty simple.

Right-click on any of your Optional Sections and choose Section Properties from the context menu. In the Default settings section of the Data tab is a radio button. Switch it from Do not include the section in the form by default to Include the section in the form by default. Click OK.

Suddenly all the little blue info icons go away and every Optional Section is now called Section. Re-Publish your form and you’ll find the auto-hiding still works perfectly and your New Item form is no longer Read-only. See? It can’t rain all the time sunshine!

Open a Link in SharePoint 2010’s Modal Dialog

Applies To: SharePoint 2010

Recently I’ve been customizing the XSLT of some of my XsltListViewWebParts. Getting all of that to work is worth another post in itself, but I wanted to talk briefly about a small frustration I had. I was customizing an announcement’s list part and I stripped out most of the nearly 1700 lines of XSLT used by default. However, one of the things I liked was being able to open the announcement in the modal dialog (sometimes called the Lightbox or the popup window):

Some searching through the autogenerated XSL for my view, I came across this section in the LinkTitleNoMenu.LinkTitle template:

<a onfocus="OnLink(this)" href="{$FORM_DISPLAY}&amp;ID={$ID}&amp;ContentTypeID={$thisNode/@ContentTypeId}" onclick="EditLink2(this,{$ViewCounter});return false;" target="_self">
	<xsl:call-template name="LinkTitleValue.LinkTitle">
		<xsl:with-param name="thisNode" select="$thisNode"/>
		<xsl:with-param name="ShowAccessibleIcon" select="$ShowAccessibleIcon"/>

I’m going to dissect what’s happening in terms of XSL for the next couple of paragraphs. If you’re just looking for the format needed, skip to the Link Format section.

Basically this is the link that gets generated inside the view’s table. The call-template element is used to fill the contents (link text), but I already had that covered and am mostly just interested in the formatting of the link to do the modal dialog magic.

Some quick experimentation shows that the onfocus call was not needed for the popup (This is what causes the menu to display and the box around the row in a standard view). Also not needed is the target=”_self” since this is equivalent to leaving the target attribute out entirely. There are really just 2 key items:


This is the URL to display in the modal dialog. In this case, it’s generated using a number of variables defined automatically. The $FORM_DISPLAY is the absolute path to the item display page. The $ID is generated using a simple Template call (we’ll come back to this). and the $thisNode/@ContentTypeId is pulling the ContentTypeId attribute from the current Row element in the $AllRows variable populated by the dsQueryResponse XML. For now, all you need to know is that it is automatically finding the display form URL and populating the necessary ID and ContentTypeId query strings for the specific item URL.


This calls the EditLink2 javascript method defined in Core.js. This extracts the link with the webpart’s ID ($ViewCounter) and shows it in the modal dialog. Then it returns false to prevent the browser from following the link like normal.

Trying to implement this exactly in my code wasn’t too hard. Unfortunately, it wouldn’t load in the popup and always just opened the page directly. Doing some searching, I came across a quick explanation and solution on technet. The EditLink2 function attempts to use a window object referenced by my webpart’s id ($ViewCounter). Whatever code sets this all up wasn’t firing in my XSL causing the window reference to be NULL and making the function default to just opening the link. Instead of tracking it down somewhere in the default generation, I did something similar to the proposed solution on technet.

Link Format

Ultimately my goal was to have a link generated using this format:

<a href=";ListId={SomeGUID}&amp;ID=SomeID&amp;ContentTypeID=SomeContentTypeID" onclick="ShowPopupDialog(GetGotoLinkUrl(this));return false;">Click Me</a>

So, I’m using the same link generation (but this could be any link). The real difference is that instead of calling EditLink2 I’m calling ShowPopupDialog. For the URL, I’m using a technique found in the EditLink2 method of calling GetGotoLinkUrl which extracts the URL from the link element.

XSL Implementation

To get this to work in XSL, you can do something similar to this:

<xsl:for-each select="$AllRows">
	<xsl:variable name="thisNode" select="."/>
	<xsl:variable name="link">
		<xsl:value-of select="$FORM_DISPLAY" />
		<xsl:call-template name="ResolveId">
			<xsl:with-param name="thisNode" select ="$thisNode"/>
		<xsl:value-of select="$thisNode/@ContentTypeId"/>

	<a onclick="ShowPopupDialog(GetGotoLinkUrl(this));return false;">
		<xsl:attribute name="href">
			<xsl:value-of select="$link"/>
		<xsl:text>View Announcement</xsl:text>

In the above XSL, we’re looping through each row returned by your view’s CAML query. We setup a link variable that builds the full HREF attribute in lines 3-11. The thing to note is the call to the ResolveId template to pull the item’s ID from the row. This is a standard template that will automatically be referenced as long as you keep the standard includes (main.xsl and internal.xsl).

Then we generate the actual html link in lines 13-17 using the $link variable we created above. This could be consolidated some, but hopefully it’s relatively easy to follow in this format.

That’s it! Now you can generate those links using XSL or follow the link format to make them on your own (like in a content editor web part).