Dynamic CSR (Client-side Rendering) Templates

As in, write the template once, drop it on the site, and then allow administrators to apply it to appropriate fields based on SPFieldType, in the browser, without ever having to edit a JavaScript file. So when I first started learning CSR, I was looking for it to be a replacement for custom field types from SharePoint 2010. But it isn’t really that. If I created an Autocomplete custom field type and deployed it, an administrator could then go through the browser and create as many instances of that field type as they wanted. But with CSR, the fields to which it applies are hard-coded in the JavaScript, which means if an administrator wants to apply a template to another field, she has to open the JavaScript and modify it. That’s not really comparable to custom fields. It’s just not as accessible for non-developer administrators. In this post, I’m going to show a utility page which implements what I’m calling Dynamic CSR, whereby an administrator can apply a template to a site column through the browser without even having to know that it’s implemented in a JavaScript file.

First I’m going to just show what the finished product looks like and how to use it. Here is the utility page:

Dynamic CSR Utility Page

When an administrator comes to this page, they can select a CSR type and add it to a field (i.e. site column). Now you can’t really just add any CSR template to any field. It’s Dynamic CSR, but not that Dynamic. For instance, my AutocompleteCSR implementation from the last post isn’t going to work particularly well if applied to a Person or Group field or a Managed Metadata field. So when you select the CSR type, the field drop down is limited to only site columns that work with the selected CSR Type (in the case of autocomplete, that would be single line of text fields), like so:

Trimmed Field Select

Now select a field and hit the ‘Add Client Template’ button, and you will get prompted with a dialog box to enter any implementation specific configuration:

Add or Edit CSR Dialog

Enter that information and hit Ok and the new field will be added to the Dynamic CSR implementation table below, complete with edit and delete buttons:

Table Showing Configured Fields for One Dynamic CSR Implementation

When you hit the save button, a couple of things happen. First, the code loops through each configured field and sets its JSLink to the appropriate JavaScript references for that implementation. Second, the configuration is written back to a file on the server, from which it is used by each of the Dynamic CSR implementations, and also by the utility page in order for it to show you all previously configured fields when you come back to it.

If you now go to a list that uses that field, the autocomplete column should work as expected, even if that list is on a sub-site. Of course, if the current user does not have permission to read from the list with the autocomplete data (or to read the JavaScript files themselves), then it won’t work. And if the CSR implementation has other dependencies that aren’t met, it won’t work. For instance, the cascading lookup implementation depends on a parent column and a relationship list. If either of these is missing, it will do nothing.

The rest of this post is going to explain parts of this solution, starting with how the CSR implementations from the previous posts had to be refactored to make this work, and then showing very briefly how to generically work with these implementations in order to do stuff like register template overrides or show all currently configured fields. The entire source for the utility page is too large to either show or explain in a blog post (but the complete source code is attached).

The Dynamic CSR Configuration

The CSR implementations I’ve shown previously just had their configuration as an array of fields (objects) at the top of the file, but that’s not going to work so well anymore. Instead, all of the configuration for each of the implementations will be combined into a single file, which will get loaded by JSLink before the implementation is loaded. The individual configurations for each implementation are exactly the same as before, an array of fields (objects), but now the outer configuration is a map of CSR implementation names to arrays of fields. Here is the complete configuration file:

This configuration is processed by the CSR implementations on forms to dynamically construct the overrides to be passed into SPClientTemplates.RegisterTemplateOverrides. It is also processed by the utility page on load to show everything that has already been configured, and overwritten by the utility page with the new configuration on each save.

The Dynamic CSR Implementations

The actual render, or pre-render, or post-render, etc. code in the Autocomplete and Cascading Lookup CSR implementations is much the same as it was before so I’m not going to show that again. But in order for the utility page and the code that dynamically builds the overrides object to be able to work with them in a generic fashion, these implementations did need to be genericised somewhat, as follows:

  1. All Dynamic CSR implementations need to be in a single JavaScript source file. This is because the code that rolls up all of the implementations is at the bottom of this file, and it needs all of the implementations to be defined before it looks through them and constructs the template overrides.
  2. Each of the implementations should be encapsulated into a single literal object instance. The cascading lookup implementation was already written this way, but the autocomplete was not.
  3. Each of the implementations needs to implement a common interface. This is so the utility page, for instance, can ask an implementation what kind of SPField types it can work with, or tell an implementation to popup it’s implementation-specific configuration dialog box, without having to know anything implementation specific.
  4. All of these implementations need to be attached to a map of implementation names to implementation instances, so the utility page or overrides building code can easily look through them. The name of the implementation, the key in this map, and the key in the configuration all must be the same.

First, there are some properties with implementation name, display name, the field types this implementation works with, and the JSLink files to load for this field implementation. The meat is in two methods, configure and getClientTemplates. Configure just pops up a dialog to get implementation-specific configuration, and then calls a callback with the newly configured node when done. getClientTemplates just returns an array of objects, one for each field, with the callbacks I want to override for that field. The pre-render and post-render methods haven’t changed at all, except the configuration is nested slightly deeper, so I’m not showing them again.

How to Work With Implementations Without Knowing Their Details

The first thing we need to do is register our template overrides with SPClientTemplates. To do that, we need to loop through our implementations and ask them what they want to override. That would look like this:

Similarly, the utility page draws it’s interface by looping through each implementation like so:

And when the user hits the add CSR button and the utility page needs to popup the implementation-specific configuration dialog, that looks like this:

And that’s really all I’m going to say about the code, because really, who’s still reading this TL;DR post anyway? And if you know HTML and JavaScript, the rest of it is more of the same anyway. A lot more of the same, but still just more of the same. In my next post I’m going to show building a more complete CSR display template, with rendering on new, edit, display, and view, plus validation and more, and plugging it into this architecture.

SetCSRConfig.zip – the complete source code.

Leave a Comment