4

I've read several walkthroughs on client-side rendering (CSR) and JSlink, and the methods to target only one list on a page instead of all lists.

I understand that I can target using two things: ListTemplateType : 100 and BaseViewID.

However, I don't understand why I am unable to target using other things, like listName or view.

Is there a way to find out other methods that I can use to target a specific list?

For example, I am currently able to target like this:

SPClientTemplates.TemplateManager.RegisterTemplateOverrides({
ListTemplateType  : 100,
BaseViewID = 1,
Footer: ...

But I wonder if there are any ways other than ListTemplateType and BaseViewID to target

2 Answers 2

5

I don't understand why I am unable to target using other things, like listName or view.

The short answer is: because that's how Microsoft designed it, and that's all they gave us. It definitely is kind of a bummer.

Keep in mind that ListTemplateType: 100 is only referring to custom lists. If you have views to other OOB SharePoint list types (Contacts, Document Library, etc.) on the same page, you would be using a different ListTemplateType value.

That being said, yes, you are still using ListTemplateType as the differentiator to keep the CSR scripts from stomping on each other.

I assume you have read about the workaround for the problem of having multiple list views all pointing at custom lists on the same page, where they all end up with ListTemplateType: 100 and BaseViewID: 1.

Now, off the top of my head (and this is completely untested by me, maybe someone else has tried this) another way you might be able to target different lists with different CSR scripts is by using content types. The SPContentType object has a JSLink property. If you create custom content types instead of just adding columns directly to lists, and then attach the different CSR scripts to the content types, and then go and add the content types to different custom (but essentially empty) lists, that might be a way to associate a particular script with a particular list.

I have no idea what would really happen in practice though if you then created a page with multiple List View Web Parts on it, each pointing to one of the different lists. But, theoretically (from what I understand), the different scripts should get pulled in because they are following the content types.

Whether or not SharePoint would then intelligently use the content types as a differentiator for selectively applying the rendering is another question.

Another way you could possibly do it, which is kind of messy but I think could work (although I don't think I'll ever try this), is to put some conditional checks into your CSR code. Something like this (pure pseudo-code):

if (ctx.CurrentListName == "my targeted list") {

    return MyCustomRendering();

} else {

    return SharePointDefaultRendering();
}

It is possible to access the default SharePoint rendering methods from inside the CSR overrides, but that's just... bleah.


To try and briefly explain how the workaround (linked to above) works, here's what's happening:

First, you add your list view web parts to the page you want them on. Then you look at the page in developer tools, and look at it in "source" mode so you are looking at the script on the page. Find the section on the bottom where SP is passing all the information about the lists. There you can see which WPQ# ID SP has assigned for each of your list views.

Armed with that knowledge, you set the BaseViewID properties in your CSR scripts to something deliberate and high, like 99, 98, etc., so you can force a match later. Say you saw that List A was assigned WPQ2. You set your override code to have BaseViewID: 99.

Then, you add another script which hijacks the default call to RenderListView. When your hijacked function gets called, you check which WPQ# the rendering call is for, quickly sneak in the BaseViewID you previously set up for your own override code, and then re-call the real RenderListView. So in the example case:

if (ctx.wpq == 'WPQ2') // we know that SP assigned List A to have WPQ2
{
    ctx.BaseViewID = 99; // force the BaseViewID to be what we set in our List A override code
}

Then SP goes "hmmm, do I have any registered overrides for BaseViewID: 99? Why yes I do." And then executes your rendering override code.

It is a very fragile workaround, because it's all based on you gaining knowledge of which WPQ# ID SP has assigned to your web parts, and if you add or remove a web part from the page, SP will re-assign those IDs, and you'll have to go back in and re-code your forced matching. (For instance, if you add or remove a web part, the List A view might no longer be assigned WPQ2, and now your substitution won't match up to the right override code anymore.)

8
  • Can't he also create a list definition in an add-in based on an existing list and use that ID to target the list? Won't it be the same as targeting the list? As mentioned here: msdn.microsoft.com/en-us/library/office/jj220045.aspx
    – Akhoy
    Oct 2, 2015 at 4:26
  • @Akhoy although the article you link to implies that you can define views with different BaseViewIDs and use custom list definition's ListTemplateType ID, the way the rendering system targets that particular list and view to apply the overrides is still through the mechanism of ListTemplateType and BaseViewID, and I think the OP's question is about how to not use those properties to target a list. Oct 2, 2015 at 14:22
  • Thanks for clarifying. OP wanted to target a custom list. So creating a custom list definition would make sure that that list is targeted, right? Just saying. Would appreciate if you could clarify :) Need more info on this.
    – Akhoy
    Oct 2, 2015 at 16:16
  • @DylanCristy Thanks a lot! I honestly don't understand the methods in the article you linked to for the workaround. I'm trying to figure it out. As Akhoy mentions, I am in fact just looking for a way to target one list in particular - I don't care how I do it, I just don't want my rendering to affect other lists on the page. And also, what is wrong with your if/else statement? It's just untidy? Oct 2, 2015 at 17:43
  • @MatthewJMammola, updated my answer with an (attempt at an) explanation. Oct 2, 2015 at 18:23
0

I had a similar problem, but could not use the solution above because I had the same list on the page in more than one list view.

My CSR was applied in the JSLink property and I happened to be doing all my processing in the OnPostRender function.

So, for me this worked:- OnPostRender: function (ctx) {
// JSLink applies to ALL "custom" lists on a page // Examine the ctx and see if THIS file is requested in THIS call if (ctx.ListSchema.JSLink.length === 0) return // No JS Link so exit var isLinked = false ctx.ListSchema.JSLink.forEach(function (v, i, r) { if (v.indexOf('transposelistview.js')) isLinked = true }) if (!isLinked) return ...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.