«

»

Sep 02

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.

22 comments

10 pings

Skip to comment form

  1. WPreston

    Thanks for the call out! :)

    Wes Preston

  2. Cimares

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

  3. sgandewar

    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. Cimares

      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.

    2. Gol4Man

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

      1. Cimares

        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. Cimares

    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.

  5. Kannan

    Hi Cimares,

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

    1. Cimares

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

  6. Dane

    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. Cimares

      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.

  7. Jagjot

    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. Cimares

      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.

  8. Mark Ferrero

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

    Mark

    1. Cimares

      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.

  9. Christy

    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. Cimares

      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.

  10. Mark

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

  11. Clem

    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. Cimares

      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/

  12. Ravi Kulkarni

    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. Cimares

      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.

  1. Multiple List View Web Parts and issues with JSLink Display Templates in SharePoint 2013

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

  2. SPC14 – Las Vegas – Wrap Up - Blog of an overweight SharePoint addict

    […] 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. Having multiple JSLink based webparts on the same page, overrides all the other templates in SP 2013 | The Relentless FrontEnd - Aackose Lal's Blog

    […] 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. JSLINK for multiple list views - FAQs System

    […] 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. Bind JSLink overrides to certain web parts only | Stefan Bauer - n8d

    […] 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. JS link 2 different templates for 2 different views of same list on 1 page | DL-UAT

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

  7. JSLINK, eine kleine Linksammlung - KOM4TEC GmbH

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

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>


*