Sharepoint CSR JSLink – View Cell Customization
February 14, 2017

The new CSR SharePoint technology introduced on 2013 version is a great feature. It gives you more flexibility customizing the list views and forms compared to the “old” XSLT customization widely used on SharePoint 2010.

I’ve decided to write about this topic as I couldn’t find a lot of information over the internet on customizing individual cells on a SharePoint list view.

There is a great post by Karsten Pohnke explaining how to achieve this by using the “Templates.Fields” json object of our custom Client Template.

The problem with this approach, and 99% of the solution we find over internet, is that using the “Tempalte.Fields” we can only apply customization to the content of the cell and not to the cell itself. If you apply, for instance, a background color to the fields you will get a nasty transparent padding inside each cell:

Sharepoint Client Side Rendering JSLink

This is because you are applying the styles to the content of the <td> and not to the <td> element.

On the other hand, there’s also a lot of information about customizing an entire row (the <tr> element) based on the value of one field, a status field for instance.

There is another awesome article by Andrei Markeev explaining in detail how CSR is applied to list views. I really recommend you to read the entire article as it gives you a clear picture of how the CSR works on SharePoint lists, not only to apply different styles, but also to work with the items data.

This is a different approach as it does not use the “Template.Fields”, but the “OnPostRender” event.

So, starting from the example on change the style of the entire line:

(function () {
   var overrideCtx = {};
   overrideCtx.OnPostRender = function(ctx) {
     var rows = ctx.ListData.Row;
     for (var i=0;i<rows.length;i++){
       var isApproved = rows[i]["_ModerationStatus"] == "Approved";
       if (isApproved){
         var rowElementId = GenerateIIDForListItem(ctx, rows[i]);
         var tr = document.getElementById(rowElementId);
         tr.style.backgroundColor = "#ada";
       }
     }
   }
   SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCtx);
 })();
 

In this example, we get the ID of the <tr> element, using the “GenerateIIDForListItem” function, so we can easily apply styles to the entire row. The problem is that if we want to customize a single cell of a specific column, the <td> elements doesn’t have an ID to be differentiated…

In my example, I have 12 choice columns and I wanted to apply a background based on the field value. The approach I took was to get the child index of each column, and then get the cell with the same index, for each item…

If we analyze the ctx object properties:

ctx.ListSchema.Field – an array with all fields present in the view, and respecting the order (the order is very important)

ctx.ListData.Row[i] –  an object with all field values of the items

tr.childNodes – the DOM child elements of the <tr> (all <td> elements)

Instead of apply a background style to the line, I will iterate through all fields of the item. Then I can easily get the <td> element associated to each Field:

 for(var j=0; j<ctx.ListSchema.Field.length;j++){
   var td = tr.childNodes[j+1];
   var fieldName = ctx.ListSchema.Field[j].RealFieldName;
   var fieldValue = ctx.ListData.Row[i][fieldName];
 }

IMPORTANT: we are adding a +1 when getting the childNode because, despite the childNodes are in order, they start with the select column (checkbox), not present in the list fields. So we need to increment 1 when accessing the <td> element.

Now, just add a switch to the field value, and apply your desired style:

for(var j=0; j<ctx.ListSchema.Field.length;j++){
  var td = tr.childNodes[j+1];
  var fieldName = ctx.ListSchema.Field[j].RealFieldName;
  var fieldValue = ctx.ListData.Row[i][fieldName];
  switch(fieldValue){
    case "Entregue": td.style.backgroundColor = "#50bb11";break;
    case "Em atraso": td.style.backgroundColor = "#dd2211";break;
    default: break;
  }
}
 

That’s it. Now the view look way better:

Sharepoint Client Side Rendering JSLink

Now, the cherry on the top :)

If you switch to quick edit mode, you’ll lose the style applied… This is because on quick edit mode, the lines (<tr> elements) doesn’t have an ID attribute, so the previous “document.getElementById” function will fail.

They have however, an IID attribute with the exact same value as ID. So I replaced the function with “document.querySelectorAll” function. This function will return an array, so I need to be sure we have exactly 1 line returned.

This is the final solution:

(function () {
 var overrideCtx = {};
 overrideCtx.OnPostRender = function(ctx) {
   var rows = ctx.ListData.Row;
   for (var i=0;i<rows.length;i++){
     var rowId = GenerateIIDForListItem(ctx, rows[i]);
     var row = document.querySelectorAll('[iid="'+rowId+'"]');
     if(row.length == 1)
       for(var j=0; j<ctx.ListSchema.Field.length;j++){
         var td = tr.childNodes[j+1];
         var fieldName = ctx.ListSchema.Field[j].RealFieldName;
         var fieldValue = ctx.ListData.Row[i][fieldName];
         switch(fieldValue){
           case "Entregue": td.style.backgroundColor = "#50bb11";break;
           case "Em atraso": td.style.backgroundColor = "#dd2211";break;
           default: break;
         }
       }
     }
   }
   SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCtx);
})();

 

Leave a Reply