ListView Web Part issues with JSLink and Display Templates – A solution?

Back at the start of August, I posted about the issues you might find using the JSLink Display Template when rendering multiple list instances on a page that all inherit from the Custom List Template. If you’re not sure what the issue is, Have a read of that post first, then come back here.

The documentation from Microsoft is still fairly minimal on JSLink and as I showed in my original post, the only way to solve this issue was through the use of Custom List Templates and a deployed solution.

This is not an option for the large majority of power users out there, even more so if you’re ‘in the cloud’, therefore a client side resolution was needed for this client side problem..

I’ve spent many hours over the last few weeks, trying to come up with PowerShell that would allow us to change the BaseViewID of the underlying List view, and trawling through the ClientTemplates.js rendering functions looking for ways to override. In the end, I’ve found a fairly simple method which is deployed in the very same file that you register your overrides in!

BIG CAVEAT! – This has not been tested to breaking point! I’ve only just discovered this and whilst it appears to work regardless of whether or not MDS is enabled, please please test it before using it in production.

How do list views render?

The key to understanding why this technique works, lies in understanding how list views are rendered by SharePoint. If you open up the Developer Toolbar in IE (Press F12), switch to the Script tab and check that you’re showing the landing page that contains your list view. (If you’re seeing start.aspx, go turn off the Minimal Download Strategy feature in your web.. then you’ll see more of the page code..)

If you scroll down to around line 850-900 You should see the javascript defining a few variables named along the lines of WPQ2ListData and WPQListSchemaData. These are basically big ole JSON objects that contain all the information about the list to be rendered.

SNAGHTML2dd845

At the bottom of this you’ll see a context object get created:-

SNAGHTML2e7bf3And then finally at the bottom of this big context object is where Microsoft calls the rendering code housed in ClientTemplates.JS

SNAGHTML3110f1

RenderListView is a function defined in ClientTemplates.JS and called by every list view web part on the page, which for some dashboards could be several times. It this ClientTemplates javascript file that is responsible for working out which templates have been registered and which should be used to render the list view.

So how do we do control our Display Template?

The key element that we need in place first is the Display Template itself. (Wes Preston does a great job of explaining these if you’re new to them..JS Link for SharePoint 2013 Web Parts – A Primer so I won’t repeat how to do this..)

The key difference that we make here, is that when we register the DisplayTemplate, we still base it off of the Custom List Template ID of 100, but give it a BaseViewID of 99. This should be a high enough number that it won’t affect any Microsoft deployed views.

	overrideCtx.BaseViewID = 99;
	overrideCtx.ListTemplateType = 100;

Below our overrideCtx object we’re going to add an ExecuteOrDelayUntilScriptLoaded block that waits until DisplayTemplates.JS has been loaded and it’s relevant functions defined.

Once it has, we then take a copy of the RenderListView function and store it in a new object, we then overwrite the original function with our own.

// Now override the RenderListView once the ClientTemplates.JS has been called
ExecuteOrDelayUntilScriptLoaded(function(){

	//Take a copy of the existing Microsoft Definition of RenderListView
	var oldRenderListView = RenderListView;

	//Now redefine RenderListView with our override
	RenderListView = function(ctx,webPartID)
	{
		//Check the context of the currently rendering List view
		if (ctx.ListTitle == "Desk List")
		{
			//Override the BaseViewID if it's the one we want.
			ctx.BaseViewID = 99;
		}
	
		//now call the original RenderListView
		oldRenderListView(ctx,webPartID);
	}

},"ClientTemplates.js");

When the ListView definition on the page calls RenderListView, it calls our code block first, which can manipulate the ctx.BaseViewID if required, or just passed the object straight through. The end result is two list views on a page, that both share the ListTemplateID of 100 and a BaseViewID of 1, yet still have custom rendering in only one of the web parts.

SNAGHTML3b1bda

Improvements?

First off, I’ve included the script block in my Display Template because I’m only defining one of them. Obviously if you’re designing a dashboard thats going to have 3-4 differently styled views, then I would extract the ExecuteOrDelayUntilScriptLoaded block into it’s own javascript file and embed that on the page separately.

You can then use this one script to affect any of the styled views, just by expanding on the logic within the overloaded RenderListView.

[important]

Since this post, and following a question on twitter, I’ve now tested this one a page with 3 different list views. Each list view requires a new BaseViewID and it seems easier to use ctx.WPQ to test against the WebPart ID rather than the list name:-

		if (ctx.wpq == 'WPQ2')
		{
			ctx.BaseViewID = 99;
		}
		else if (ctx.wpq == 'WPQ3')
		{
			ctx.BaseViewID = 98;
		}
		else if (ctx.wpq == 'WPQ4')
		{
			ctx.BaseViewID = 97;
		}

 
The override just lived in the first display template, but you could place it in it’s own file and add it to the JSLink.

An updated version of this display template is available on #SPCSR

As well as my new debug templates here.
[/important]

 

Summary

I think this is probably about the best option I could have come up with to solve this issue, I can’t see a more efficient way of doing it without re-writing some of the MS javascript so I know this will be what I run with for now.

I really hope this helps some people who have been struggling with this particularly thorny issue and please by all means if you have any comments, just grab me on twitter.. @Cimares

You can get the full display template code here.

Regards

Paul.

27 comments

11 pings

Skip to comment form

  1. Thanks for the call out! 🙂

    Wes Preston

  2. You’re welcome Wes, your guide and SPC session gave me a great start.

  3. hello.

    This is nice tutorial really. Helped me a lot.
    I am having another issue related to ViewStyleID… I have setup a ‘Shaded’ View style on SharePoint list view which will have ID of 17. and using some functionality in JS Link to render column as image instead of text. As soon as I use this js link default rendering of Shaded style goes away and UI looks unformatted. I would like to keep the style as default Shaded View gives. I cant completely create such style in my js link since I need to have default sort functionality on the columns too. have you came across this scenario ever?

    1. When you say it looks unformatted, do you mean it just looks like a standard list view on the page? If so, then that usually means there’s an error in your JavaScript and SharePoint decides to ignore your Display Template and use the default instead.

      • Gol4Man on Sat 31 Jan 15 at 6:39 pm
      • Reply

      Did you ever receive an answer to your question / issue? I am dealing with the same thing and cannot figure it out.

      1. The poster above never came back with more info. From the sounds of it, if your list view is coming back unformatted, then there is probably a mistake in your JavaScript. Best bet is to step through the code.

  4. Hi Gol4Man, I use the method I show above quite heavily and it does what I need it to do. going by the conversations I’ve had around the community, this is Display Templates working as intended and it’s not likely to change anytime soon.

    Stefan Bauer has posted an alternative method which is slightly more generic and a little more portable. You can read about it on his blog here. http://www.n8d.at/blog/bind-jslink-overrides-to-certain-web-parts-only/

    Paul.

    • Kannan on Thu 12 Mar 15 at 12:36 pm
    • Reply

    Hi Cimares,

    Thanks for posting this article and it helped me a lot in fixing the issue. you are a champ.

    1. Thanks for your comments Kannan, It’s good to know it’s helping people.

    • Dane on Wed 22 Apr 15 at 4:54 am
    • Reply

    Hi this fix worked for me, but when i try to “sort” a list that is also grouped it freezes on “Working on it”

    ie. if there is a list that is grouped on column A, and i try to sort on column B it freezes

    1. Hi Dane, thanks for letting me know. As I said I haven’t tested this in all cases. I’ll try and get some time this weekend to have a look and see if I can resolve that.

      Paul.

    • Jagjot on Mon 8 Jun 15 at 11:28 am
    • Reply

    I’m facing the same issue and followed the steps but it did not fix it. Below is scenario
    I created a list and added a JSLink file to it. Added the same as an Apppart on the page and it works perfectly.
    Then i created another list (not related to first list) added a seperate JSLink file to it and its working perfectly, however if i embed both of them on the same page the first jslink stops working and is overridden by the second JSLink. I tried the above approach but still the same issue
    Can you help?

    Note: I’m overriding the complete list using JSLink in both cases on just Fields aslo i want this in JSLink & not in display template.
    Tried this as well as: http://www.n8d.at/blog/bind-jslink-overrides-to-certain-web-parts-only

    1. Sorry Jagjot, for some reason I’m not receiving comment notifications!

      If you’re creating multiple Display Template JavaScript files, you need to ensure that you’re not using the same variable and function names. The best way to do that is to create a sub namespace for each one.. It does make the file slightly more arduous to type as you have to namespace all the functions with a longer name but it will ensure separation. (I’ll do a separate blog post on this later this week!)

      Alternatively, just create a brand new namespace for each one (All of my samples create the namespace PFH in the line

      var PFH = PFH | {}

      You could just create a new namespace for each one javascript file.

      Paul.

        • aZoed on Fri 12 Aug 16 at 8:00 am
        • Reply

        Hello
        This is a great great post and a noob like me finally figured it out how to implement it finally. Did you by any chance do the post that you mentioned in reply to the above query? I am now trying to apply the override to two different lists on my page and would like some pointers to get me there.

    • Mark Ferrero on Wed 10 Jun 15 at 8:50 pm
    • Reply

    What if you want to format more than one of the web parts with JS Link?

    Mark

    1. Hi Mark, Apologies for the late reply as I’m not getting notifications.. Take a look at my answer to Jagjot above, he’s having the same problem.

    • Christy on Wed 17 Jun 15 at 3:54 am
    • Reply

    Thanks for sharing! This seems like it should solve my problem; I am trying to use two list view web parts to render two different views of the same list on a single page. However, using your sample code, I keep getting the error that ‘RenderListView’ is undefined. I have verified that the ClientTemplates.js file is getting loaded. Has anyone else encountered this issue?

    1. Again, apologies as I haven’t been receiving notifications for comments for some reason!

      That was the error I was getting until I added the ExecuteOrDelayUntilScriptLoaded section was added as the ordering of JavaScript files on SharePoint pages isn’t guaranteed.

      I would double check that you’ve got the elements inside the ExecuteOrDelayUntilScriptLoaded correct.. Send me a message on Twitter Christy (I’m @Cimares) and I’ll take a look at your script file if you haven’t resolved it.

      Paul.

        • aZoed on Fri 12 Aug 16 at 8:02 am
        • Reply

        Hello
        This is a great great post and a noob like me finally figured it out how to implement it finally. Did you by any chance do the post that you mentioned in reply to the above query? I am now trying to apply the override to two different lists on my page and would like some pointers to get me there.

        1. Hi there,

          If both of those lists are the only ones on the page, and they both have the same List Template ID, then you don’t need to do anything, this fix is to stop the display template being applied to both.

          If you want it to apply to 2 out of more list views on the page, then just make sure they have the same BaseViewID set in the logic that checks against WPQ or ListName.

          Paul.

  5. It is July 2015 and your blog is the only article that provide solution. Thank you!

    • Clem on Fri 13 Nov 15 at 6:19 am
    • Reply

    Hi,

    Great post, very new to SharePoint and pretty rusty at js, but it worked for me!

    Now for the question to reveal my true ignorance: why hasn’t jQuery seemed to load by the time PostRenderCallback function has triggered?

    I solved the issue(?) by wrapping my jQuery inside PostRenderCallback in the below to double check everything has loaded:

    document.addEventListener(“DOMContentLoaded”, function(event) {

    });

    But I am still totally confused as other jslink files I had created I didn’t seem to need anything special. I’m not even sure it is your code, just something perhaps with multiple lists on one page?

    Thanks again!

    1. Hi Clem,

      Generally the JSLink files are loaded in the head of the page when you add them to the JSLink webpart property and they’re called at a specific point by the SharePoint process, so it has a lot of control when they’re called. When you use an external JavaScript file such as jQuery, you lose that control and have to do one of two things. One is to register your script to be run when the DOM is complete, which is pretty much what you’ve done. The other alternative is to register jQuery as a Script on Demand dependency so that it ensures jQuery is loaded prior to you calling it.

      Elio Struyf has a great blog post on how this works with Search display templates and you should be able to adapt the same methods to work in your JSLink display templates too. http://www.eliostruyf.com/correctly-including-scripts-display-templates/

    • Ravi Kulkarni on Sun 6 Mar 16 at 6:05 am
    • Reply

    Hey,
    Trying out the same thing but itis not working at my end.
    I am not creating the JSlink,rather using client side rendering and calling it out from MasterPage.
    It is overriding the first webpart bu it fails to override the other webparts on the Page.
    Using exactly your same code

    1. Hi Ravi,

      I can’t quite picture what you mean. You’re calling the display template file from your Masterpage and it’s rendering one web part correctly and not affecting the others? if that’s the case then it’s doing exactly what it’s supposed to do. This particular work around is to stop a JSLink file affecting more than the one web part on the page.

      Paul.

    • Paul D on Tue 19 Dec 17 at 8:34 pm
    • Reply

    Hi Paul,

    I’m a new JavaScript and CSR and have managed to create a number of JavaScript Display templates that render content as required. The templates have been configured to target List Templates IDs (100-Custom FAQS, 101-Documents, 103-Links) and work individually when I create the views in the respective lists.

    The problem lies when I add the views to a page using a OOTB List Web Part. I am not using JSLink, instead I am simply selecting a view that uses a JavaScript Display Template. The Web Parts work well when one Display Template is executed, but when I have several Web Parts configured using different Views/Display Templates, the Display Template used for the last Web Part (added) is applied to all Web Parts.

    My understanding is the rendering issue is only when the list template id was the same (i.e custom) If the IDs were different they should be rendered ok?

    I have tried using separate namespaces in the JavaScript Display Templates (not sure I have done this correctly), but it doesn’t seem to make any difference. I have example code for you to review if required.

    I appreciate you are busy with your own challenges, and any help will be most appreciated.

    Kind Regards

    Paul

    1. Hi Paul,

      Apologies only just spotted your comment amongst the spam filters!

      I would suggest that you take a look at using the developer tools in IE or Chrome to set some breakpoints in your Display Templates. It does sound like for some reason it’s applying the template regardless of the TemplateID that you’ve assigned as that behaviour you’re seeing is exactly what this post is supposed to help prevent! In theory you could use the same logic in your Display Templates that I’ve used here, but you would need to duplicate it across all of your display templates to ensure that your new overridden base render is always called. This is a little more difficult when the JSLink is directly embedded in the views. Might be worth breaking the display templates out just on the web views, but setting custom views on the webpart and calling the JSLink directly.

      Paul.

  1. […] ListView Web Part issues with JSLink and Display Templates – A solution? » […]

  2. […] I also managed to meet up with Wes Preston. I was introduced to List View Display Templates by Wes at SPC12 and it was his original blog posts that led me down the rabbit hole and got me digging into the power of display templates. Unfortunately I wasn’t able to attend his session this time as it clashed with a session that I really needed to attend, however I did find out that he gave me a shout out for the work I did on fixing the clashing Templates issue. (Original blog here) […]

  3. […] Hunt (@Cimares) has the solution for this scenario wonderfully detailed out here.This solution works and you can do an IF condition check to load the templates corresponding to […]

  4. […] view it’s applied also for the other view. I search a lot in the net and i find this tutorial http://www.myfatblog.co.uk/index.php/2013/09/listview-web-part-issues-with-jslink-and-display-templa… but i still don’t understand how to build my own jsfile and apply it […]

  5. […] which web part called the field override. Paul Hunt posted a solution in his blog post “ListView Web Part issues with JSLink and Display Templates – A solution?“. This solution works great, but what I was looking for is a more generic approach. One thing […]

  6. […] need to set the BaseViewID properties to different values, such as 99 and 98. See this blog for more […]

  7. […] Hunt beschreibt, wie man mit dem JSLINK bei mehreren Webparts auf einer Seite umgeht und bietet außerdem einige interessante Templates dazu […]

  8. […] to multiple web parts, but the styling was throwing errors. I did some research and found this article that was a big help. However, it took some trial and error for me to completely fix the issue. I […]

Leave a Reply

Your email address will not be published.

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.