Register CSR-override on MDS enabled SharePoint 2013 site

Both CSR [Client-Side Rendering] and MDS [Minimal Download Strategy] are new concepts in SharePoint 2013.  I recently had a chance to work on an issue concerning CSR and MDS, which I thought I’d share through this post so that it is helpful for the developer community.

If you already know what CSR is or wondering what it is… take a look at: https://msdn.microsoft.com/en-us/library/jj220061.aspx.  This provides an outline on CSR so you can imagine what it is capable of and also provides a sample to see it in action.

Now to the problem we ran into and the fix for it.

When you download the sample provided through the link and deploy it to a SharePoint 2013 team site as is, you’ll notice that you see a new CustomFieldList list.  If you browse to it, you’ll see the list as shown in Image 1 below.  That’s CSR in action!  Oh and remember to reset IIS after you deploy this solution.  Since we are deploying a field type, that’s a requirement.  Or else, you’ll see an error complaining the field type is not properly installed, which will lead you in the wrong direction should you choose to troubleshoot it!

 

image

This all works well! Now to the actual issue.  If you click on any other link such that it would navigate you out of this list (for e.g., click the Home link in the left navigation) and hit the CustomFieldList back, you’ll see same list as shown in Image 2 below.

image

Oops, the color are gone!

Apparently, this is because MDS is enabled by default on a SharePoint 2013 team site.  I’ll leave you to explore more on MDS as a feature, but I will try to explain what happens here.  When the list view page was first rendered, the MDS system receives the custom javascript for the first time.  It then, puts this javascript in a list (let’s call it “already executed javascripts” for fun).  When subsequent pages are requested, MDS checks its own list of “already executed javascripts” and if the page being requested requires execution of a javascript, which MDS already has on its list, it simply will not execute it again.  This approach has its own performance gain and there are scenarios where you’d want this approach.  Explore more on MDS for learning those, but for the scenario in hand, this is clearly not what you want.  You want the CSR script to execute every single time.  So, how to achieve that?

You can disable MDS which is a web feature as shown in Image 3 below.

image

But what if you want the best of both the worlds?

You have to make use of a call out to RegisterModuleInit() function on which documentation is currently scarce.  This function will tell the MSD infrastructure to exclude a particular javascript file with an entry point signature (basically a entry point function) from MDS.  If you pop open the CSRFieldType.js file, it will look like the below.

 (function () {
     var favoriteColorContext = {};
  
     // You can provide templates for:
     // View, DisplayForm, EditForm and NewForm
     favoriteColorContext.Templates = {};
     favoriteColorContext.Templates.Fields = {
         "FavoriteColorField": {
             "View": favoriteColorViewTemplate
         }
     };
  
     SPClientTemplates.TemplateManager.RegisterTemplateOverrides(
         favoriteColorContext
         );
 })();
  
 // The favoriteColorViewTemplate provides the rendering logic
 //  the custom field type when it is displayed in the view form.
 function favoriteColorViewTemplate(ctx) {
     var color = ctx.CurrentItem[ctx.CurrentFieldSchema.Name];
     return "<span style='background-color : " + color +
         "' >&nbsp;&nbsp;&nbsp;&nbsp;</span>&nbsp;" + color;
 }

You need to register this file for CSR-override on MDS enabled sites.  You need to do two modifications to achieve this.

First, you need to change the anonymous entry point function to a function with an entry point signature.  Then, you need to call RegisterModuleInit() function to register an override of this code on MDS enabled sites.  Below is how the same CSRFieldType.js file looks with these changes.

 RegisterModuleInit("CSRAssets/CSRFieldType.js", RegisterFavoriteColor); // CSR-override for MDS enabled site
 RegisterFavoriteColor(); //CSR-override for MDS disabled site (because we need to call the entry point function in this case whereas it is not needed for anonymous functions)
  
 function RegisterFavoriteColor() {
     var favoriteColorContext = {};
  
     // You can provide templates for:
     // View, DisplayForm, EditForm and NewForm
     favoriteColorContext.Templates = {};
     favoriteColorContext.Templates.Fields = {
         "FavoriteColorField": {
             "View": favoriteColorViewTemplate
         }
     };
  
     SPClientTemplates.TemplateManager.RegisterTemplateOverrides(
         favoriteColorContext
         );
 }
  
 // The favoriteColorViewTemplate provides the rendering logic
 //  the custom field type when it is displayed in the view form.
 function favoriteColorViewTemplate(ctx) {
     var color = ctx.CurrentItem[ctx.CurrentFieldSchema.Name];
     return "<span style='background-color : " + color +
         "' >&nbsp;&nbsp;&nbsp;&nbsp;</span>&nbsp;" + color;
 }

To explain the RegisterModuleInit() call out a bit…

The first parameter is the path to the javascript file relative to the _layouts folder.  Since this solution deploys the javascript file into a folder under the _layouts virtual directory, you have provided that relative path.  The second parameter is the entry point function.  The other call to RegisterFavoriteColor() is to ensure this javascript works both on MDS enabled and disabled sites.

That’s it! Once the CSR javascript is redesigned in this fashion, deploy it, reset IIS, clear browser cache and your CSR javascript should execute always.

Oh yes, and if you want the javascript to be deployed to a SharePoint container (like a document library or master page gallery etc.,), the RegisterModuleInit() call should change as well.  Here’s an example, of the function call when the javascript file is put at the root of the master page gallery.

 RegisterModuleInit("/_catalogs/masterpage/CSRFieldType.js", RegisterFavoriteColor); // CSR-override for MDS enabled site

I haven’t been able to explore much into this approach, but I understand this will probably be the approach for solutions targeted towards O365.  So, I will dig into it and pull up another post when I figure it out.

Hope this post helps!

Cross post from https://blogs.msdn.com/sridhara