Targeted JSLink for List View Web Parts

Introduction

Standard Client Side Rendering (CSR) is a powerful technology introduced in SharePoint 2013. Out Of The Box (OOTB) you can apply this technology to list view web parts through use of the JS Link property. Using this technique, developers can quickly and easily apply display logic through JavaScript.

Unfortunately, despite its continued support in SharePoint 2016 and Office365, CSR with list view web parts still suffers from a major flaw. When you have multiple web parts that display list items from lists that share a ListTemplateType and BaseViewID, OOTB CSR provides no way to correctly target your display logic (JSLink) to individual web parts.

How to Get the Code

The example code used in this document can be found in full as part of the csrShim repository:
https://github.com/thechriskent/csrShim/tree/master/Examples/Multiple%20List%20Views

The full project can be found on GitHub:
https://github.com/thechriskent/csrShim

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

The Problem

When a user adds 2 or more web parts displaying list items from a list that share a ListTemplateType and BaseViewID, standard CSR has no way of distinguishing between the web parts.

The result is that if only a single web part has a JS Link property specified, all matching web parts will be drawn with that logic (even ones intended to use the OOTB display!). If more than one web part has the JS Link property, then only the last one loaded will be applied.

This is especially problematic because custom lists all share a ListTemplateType of 100 and will present with a BaseViewID of 1. This issue often surprises developers that have developed their web part in isolation where they worked perfectly just to have them break entirely when placed on a page with other web parts.

A Demonstration

  1. We will add a web part using JSLink as configured in the List View Client Side Rendering (JSLink) Primer to have a web part using JS Link (The example code can be downloaded from the repository mentioned above):
    Single CSR
    This is a pretty standard team site page with a Site Feed, a Document Library, and a custom list with JSLink applied using standard CSR (Hall of Fame)
  2. Now if we add another Custom List web part (just an OOTB view):
    Broken CSR
    Immediately we see the someList web part is full of errors (these are JS errors from missing fields where the CSR attempted to apply the JSLink file)
  3. Removing the Hall Of Fame web part from the page fixes the someList web part:
    No CSR Fixed

There are many solutions for this to be found online. Most of these solutions are hacky workarounds at best, at worst they create fragile code and dependencies on management code outside of the web parts themselves.

It is often suggested to “override” the standard CSR template registration function and then create your own system to route CSR requests by dynamically changing the BaseViewID of the ContextInfo (ctx) objects. This technique requires you to have knowledge ahead of time of all possible web parts on the page or to have some additional way to uniquely identify/register your parts. The override is just taking advantage of JavaScript’s ability to alter objects you don’t own and introduces serious risk to your solutions (upgrades, users adding unknown web parts, and more).

The Solution

Fortunately, there is a solution that addresses many of the risks laid out above. The best part is that it can be independently implemented for individual web parts. These web parts never need to know or care about other web parts on the page (no management system required).

The solution is to use csrShim with your list view web parts. csrShim was originally developed to bring CSR capabilities to web parts without JS Link properties (Content by Query Web Parts and XMLViewer), but it can easily be applied to XSLTListView web parts. When doing so, you can specify a BaseViewID that is not tied to the original value allowing you to target web parts very specifically to CSR templates!

In addition, using csrShim this way allows you to add as many web parts to the page with the same underlying ListTemplateTypes and BaseViewIDs as needed and each can direct which CSR (JSLink) should be used for themselves. This technique can even be used alongside the standard CSR JS Link usage without causing issues for those parts or themselves.

A Demonstration

  1. Going back to our csrSad page from above, let’s add the Hall Of Fame web part back to the page but this time we’ll skip specifying the JS Link property:
    No JSLink
    When the JS Link property is not used, the OOTB views of custom lists can live side by side on a single page. But that’s not very exciting!
  2. Instead of specifying the JS Link property, we will specify the csrShim Parameters of BaseViewID and JSLink:
    Parameters
  3. Now when we refresh the page:
    WorkingWow
    Voila, someList web part is just fine! (If you don’t have any profile pictures showing up be sure you used the halloffame.js for this example)
  4. We can even add additional views of the Hall of Fame list:
    Multiple Hall Of Fame
    We could apply CSR to this web part without issue as well by simply specifying a different BaseViewID (assuming we wanted it to render differently).

Benefits

  • A single property is all that’s required to distinguish web parts (BaseViewID)
    • This property is exported with the web part so that it can be added to the web part gallery and safely added to any unknown page without causing conflict
  • Utilizes OOTB XSL system
  • Utilizes OOTB Rendering system

Drawbacks

  • Some properties must be accessed differently
    • An example can be seen with how the user id was pulled to generate the link for the hall of fame. Standard CSR provides an array of user objects with individual properties. csrShim provides multiple strings for those values. Using the ctx.csrShim boolean property, you can easily create a JSLink file that can handle either:
var sip, userId;
if(ctx.csrShim){
    sip = ctx.CurrentItem["Person.sip"];
    userId = ctx.CurrentItem["Person.id"];
} else {
    sip = ctx.CurrentItem.Person[0].sip;
    userId = ctx.CurrentItem.Person[0].id
}
  • Reliance on another component (csrShim)
    • To solve this problem, you would have to introduce something, likely something requiring more overhead and support issues
  • csrShim only returns a subset of properties that standard CSR returns (all list values are returned) but nearly every property used in rendering is included