Assign Column Values During Runtime And Highlight The Rows Using Client Side Rendering

Recently, I had to implement a lot of Client Side Rendering in one of my projects. One of the requirements was to dynamically compare the two column values at the run time and assign the third column a value based on it. In addition to it, based on the new value assigned, the row had to be highlighted with different colors. Conditionally, assigning the value was fairly simple as mentioned here:

However, I had to color the code and the rows based on the value as well. Combining both the functionality was a challenge. Thanks to Andrey for helping me out here. We will see in detail, how we can implement it in this article.

products

Client side Rendering is a powerful option to modify the list views and list forms. It simply means that the data is transformed and displayed, using Client side technologies like HTML and JavaScript. Prior to SharePoint 2013, in case of any requirements to modify the list views, we had to use SharePoint Designer and XSLT formatting.

Essentially, JSLink taps into the list view rendering and overrides properties that govern the list view look and feel. Some of the properties that can be overridden are:

  • OnPreRender
  • OnPostRender
  • View
  • Body
  • Item
  • Fields
  • Header
  • Footer

In this article, we will be overriding OnPostRender and Fields properties. "OnPostrender" allows us to modify the list view, once the view has been rendered. ‘Fields’ property helps us to override the styling behavior during rendering time. Similarly, each of the properties can be overridden during run time to accomplish different list view modifications and at different list view place holders.

Let’s see how we can modify the List view using JSLink and highlight the rows conditionally.

JSLink Implementation

  • The main entry point of Client Side Rendering is SPClientTemplates.TemplateManager.RegisterTemplateOverrides. Prior to calling this function, we will define which are the JSLink properties. We will be overriding along the rendering process:
    1. var overrideCurrentContext = {};  
    2. overrideCurrentContext.Templates = {};  
    3. overrideCurrentContext.Templates.Fields =  
    4.   {  
    5.     'Sales_x0020_Progress':  
    6.   {  
    7.         'View': HighlightProductRows  
    8.     }  
    9. };  
    10. overrideCurrentContext.OnPostRender = postRenderHandler;  
    Here, we are overriding the View and OnPostRender properties of the client context. Once we have specified the overriding property, call the RegisterTemplateOverride method, given below:
    1. SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCurrentContext);  
  • The main logic is added within the function ‘HighlightProductRows.' This function will compare Total sales, Sales target column values and return a value to the Sales Progress column. Since this method is assigned as an override of ‘Fields’ property, it will run for each of the single list items within the list.

    Ctx.CurrentItem.ColumnName will get the value of the column. Since it is a number field, it has an inherent comma for the values greater than 1000. To do numerical comparisons, we have to remove a comma as given below:
    1. var totalSalesVal =ctx.CurrentItem.Total_x0020_Sales.replace(",""");  
    Once we have a comma free value, we will compare two values (totalSalesVal, targetSalesVal) and assign 'Sales_x0020_Progress; a return value, based on the result:
    1. function HighlightProductRows(ctx)  
    2.   
    3.     var totalSalesVal = ctx.CurrentItem.Total_x0020_Sales.replace(",""");  
    4.     var targetSalesVal = ctx.CurrentItem.Sales_x0020_Target.replace(",""");  
    5.     var displayHtmls =  
    6.     {  
    7.         'LongWay''Long way to target !',  
    8.         'Reaching''Reaching Target',  
    9.         'OnTarget''On Target'  
    10.     };  
    11.     return displayHtmls[AnalyseSalesValues(totalSalesVal, targetSalesVal)];  
    12. }  
    13.   
    14. function AnalyseSalesValues(totalSalesVal, targetSalesVal)  
    15.   
    16.     if (parseInt(totalSalesVal) > parseInt(targetSalesVal))  
    17.     {  
    18.         return "OnTarget";  
    19.     } else if (parseInt(targetSalesVal) - parseInt(totalSalesVal) <= 1000)  
    20.     {  
    21.         return "Reaching";  
    22.     } else  
    23.     {  
    24.         return "LongWay";  
    25.     }  
    26. }  
  • On Post Render, we will highlight the rows, based on the value assigned to Sales Progress:
    1. function postRenderHandler(ctx)  
    2.   
    3.     var statusColors =   
    4.     {  
    5.         'LongWay''#FFF1AD',  
    6.         'Reaching''#FFD800',  
    7.         'OnTarget''#01DF3A'  
    8.     };  
    9.     var rows = ctx.ListData.Row;  
    10.     for (var i = 0; i < rows.length; i++)  
    11.     {  
    12.         var totalSalesVal = rows[i]["Total_x0020_Sales"].replace(",""");  
    13.         var targetSalesVal = rows[i]["Sales_x0020_Target"].replace(",""");  
    14.         var status = AnalyseSalesValues(totalSalesVal, targetSalesVal);  
    15.         var rowId = GenerateIIDForListItem(ctx, rows[i]);  
    16.         var row = document.getElementById(rowId);  
    17.         row.style.backgroundColor = statusColors[status];  
    18.     }  
    19. }  
    Here, we are using a for loop to iterate through each of the list item using ctx.ListData.Row . Our aim is to read 'Sales_x0020_Progress' column value. Highlight the row, if required. However, there is a problem. We are calculating Sales Progress values during run time but we have not yet written it to the list, as the rendering is not complete. We are midway through the rendering process and we have to highlight the row, based on the value, which is not yet there in the column. Unfortunately, we will have to call the ‘AnalyseSalesValues’ method, which was used previously. Once, again to get the value,  we will highlight the row as shown in Line No 14 above.

    By defining the Conditional Assignment of the column value by overriding the fields property and highlighting the row in PostRender Handler, we have achieved our purpose.

    Full Code

    1.  (function()   
    2.   {  
    3.      var overrideCurrentContext = {};  
    4.      overrideCurrentContext.Templates = {};  
    5.      overrideCurrentContext.Templates.Fields =  
    6.        {  
    7.          'Sales_x0020_Progress':  
    8.        {  
    9.              'View': HighlightProductRows  
    10.          }  
    11.      };  
    12.      overrideCurrentContext.OnPostRender = postRenderHandler;  
    13.      SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCurrentContext);  
    14.  })();  
    15.   
    16.  function AnalyseSalesValues(totalSalesVal, targetSalesVal)  
    17. {  
    18.      if (parseInt(totalSalesVal) > parseInt(targetSalesVal))  
    19.      {  
    20.          return "OnTarget";  
    21.      } else if (parseInt(targetSalesVal) - parseInt(totalSalesVal) <= 1000)  
    22.      {  
    23.          return "Reaching";  
    24.      } else  
    25.      {  
    26.          return "LongWay";  
    27.      }  
    28.  }  
    29.   
    30.  function HighlightProductRows(ctx)  
    31. {  
    32.      var totalSalesVal = ctx.CurrentItem.Total_x0020_Sales.replace(",""");  
    33.      var targetSalesVal = ctx.CurrentItem.Sales_x0020_Target.replace(",""");  
    34.      var displayHtmls =  
    35.      {  
    36.          'LongWay''Long way to target !',  
    37.          'Reaching''Reaching Target',  
    38.          'OnTarget''On Target'  
    39.      };  
    40.      return displayHtmls[AnalyseSalesValues(totalSalesVal, targetSalesVal)];  
    41.  }  
    42.   
    43.  function postRenderHandler(ctx)  
    44. {  
    45.      var statusColors =  
    46.      {  
    47.          'LongWay''#FFF1AD',  
    48.          'Reaching''#FFD800',  
    49.          'OnTarget''#01DF3A'  
    50.      };  
    51.      var rows = ctx.ListData.Row;  
    52.      for (var i = 0; i < rows.length; i++)  
    53.      {  
    54.          var totalSalesVal = rows[i]["Total_x0020_Sales"].replace(",""");  
    55.          var targetSalesVal = rows[i]["Sales_x0020_Target"].replace(",""");  
    56.          var status = AnalyseSalesValues(totalSalesVal, targetSalesVal);  
    57.          var rowId = GenerateIIDForListItem(ctx, rows[i]);  
    58.          var row = document.getElementById(rowId);  
    59.          row.style.backgroundColor = statusColors[status];  
    60.      }  
    61.  } 
  • Let’s see how to add the code as JSLink to the list view. Save the code as a JS file and upload it to one of the Libraries, say: Site Assets.
  • Go to the edit page of the list view by appending the URL “? ToolpaneView=2” at the end of the list view’s .ASPX URL.
  • Click Edit Web part for the list view. Under Miscellaneous section, there is a text box to enter JSLink.
  • Add the relative URL of the JS file after ~site or ~ sitecollection, depending upon the location of the Site Assets Library (or any other repository), where you have uploaded the JS file.

    file
    Click Apply. This will apply JSLink to the list view.

Output

Output
Thus, we have conditionally assigned a value to Sales Progress column. Based on the value, we have highlighted the rows.