2

I am working on a Team site collection inside SharePoint server 2016. I have the following JSLINK, which will show the sum of a column inside my list view:-

var _totalValue = 0.0;
var _totalColumn = 27;  // Specify total number of columns in list view.
var _columnIndex = 10;  // Specify the index of the column where you want to display sum values. (i.e. index for first column = 1)

(function () {

    var calculatedFieldCtx = {};  

    calculatedFieldCtx.Templates = {};

    calculatedFieldCtx.Templates.Fields = {
        "Yearof2016MLC": {
            "View": CalculatedFieldViewTemplate
        }
    };

    calculatedFieldCtx.OnPostRender = [];
    calculatedFieldCtx.OnPostRender.push(function()
    {  
        // Specify id of the list view table for which you want to display sum values. 
        var HTMLTableElement = document.getElementById("{B3D883A5-6962-47FD-BDEF-BB83FF4C78EA}-{C86BA145-8C22-47E8-938C-11B8C7F855C3}");

                var tbodyElement = document.createElement('thead');
                tbodyElement.id = "customAggWPQ";

                var trElement = document.createElement('tr');

                var tdElement;
                for(var i = 1; i <= _totalColumn; i++) {
                        tdElement = document.createElement('th');
                        tdElement.id = "tdElement" + i;
                        if( i == _columnIndex) {
                              tdElement.innerHTML = "<b>Sum= " + numberFormat(_totalValue) + "</b>";
                        }
                        trElement.appendChild(tdElement);
                }

        tbodyElement.appendChild(trElement);
        if(document.getElementById("customAggWPQ") == null) {
                HTMLTableElement.insertBefore(tbodyElement,HTMLTableElement.firstChild.nextSibling);
        }
        else {
                document.getElementById("tdElement" + _columnIndex).innerHTML = "<b>Sum= " + numberFormat(_totalValue) + "</b>";
        }
        _totalValue = 0.0;
    })

    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(
        calculatedFieldCtx
    ); 
})();


function CalculatedFieldViewTemplate(ctx) {       
    _totalValue += parseFloat((ctx.CurrentItem.Yearof2016MLC).replace(',', ''));

    return ctx.CurrentItem.Yearof2016MLC;
}

var numberFormat = function(number) {
        var sDelimeter = ',';
        number = Math.round(parseFloat(number) * 100) / 100;
        var numStr = ('_' + number).replace('_', '');
        var buffer = [];
        for (var i = 0, len = numStr.length; i < len; i += 1) {
            buffer.push(numStr.substring(len - 1 - i, len - i));
            if (((i + 1) % 3 == 0) && (i != len - 1)) {
                buffer.push(sDelimeter);
            }
        }

        return buffer.reverse().join('').replace(",.", ".");
};

I got the code from the following link Link. now when I first navigate to the list view the new Sum column will be shown correctly. but if I click on let say the list view name, then the sum will disappear, but if i do a column based filtering the sum will be updated... and if I want to show the column back I need to do a refresh of the web page.. so can anyone advice on this? I think the problem is related to the fact that doing an Ajax update for the list view will not force the JSLINK to fire.

EDIT Now i editted my JSlink as follow, based on @Dylan reply:-

var _totalValue = 0.0;
var _totalColumn = 27;  // Specify total number of columns in list view.
var _columnIndex = 10;  // Specify the index of the column where you want to display sum values. (i.e. index for first column = 1)

(function myCSRRendering () {

    var calculatedFieldCtx = {};  

    calculatedFieldCtx.Templates = {};

    calculatedFieldCtx.Templates.Fields = {
        "Yearof2016MLC": {
            "View": CalculatedFieldViewTemplate
        }
    };
 SPClientTemplates.TemplateManager.RegisterTemplateOverrides(calculatedFieldCtx); 
    calculatedFieldCtx.OnPostRender = [];
    calculatedFieldCtx.OnPostRender.push(function()
    {  
        // Specify id of the list view table for which you want to display sum values. 
        var HTMLTableElement = document.getElementById("{B3D883A5-6962-47FD-BDEF-BB83FF4C78EA}-{C86BA145-8C22-47E8-938C-11B8C7F855C3}");

                var tbodyElement = document.createElement('thead');
                tbodyElement.id = "customAggWPQ";

                var trElement = document.createElement('tr');

                var tdElement;
                for(var i = 1; i <= _totalColumn; i++) {
                        tdElement = document.createElement('th');
                        tdElement.id = "tdElement" + i;
                        if( i == _columnIndex) {
                              tdElement.innerHTML = "<b>Sum= " + numberFormat(_totalValue) + "</b>";
                        }
                        trElement.appendChild(tdElement);
                }

        tbodyElement.appendChild(trElement);
        if(document.getElementById("customAggWPQ") == null) {
                HTMLTableElement.insertBefore(tbodyElement,HTMLTableElement.firstChild.nextSibling);
        }
        else {
                document.getElementById("tdElement" + _columnIndex).innerHTML = "<b>Sum= " + numberFormat(_totalValue) + "</b>";
        }
        _totalValue = 0.0;
    })

    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(
        calculatedFieldCtx
    );

})();


function CalculatedFieldViewTemplate(ctx) {       
    _totalValue += parseFloat((ctx.CurrentItem.Yearof2016MLC).replace(',', ''));

    return ctx.CurrentItem.Yearof2016MLC;
}
// register for MDS enabled sites
RegisterModuleInit('http://servername/offices/Shared%20Documents/sum3.js', myCSRRendering);

// fallback for non-MDS enabled sites
myCSRRendering(); 
var numberFormat = function(number) {
        var sDelimeter = ',';
        number = Math.round(parseFloat(number) * 100) / 100;
        var numStr = ('_' + number).replace('_', '');
        var buffer = [];
        for (var i = 0, len = numStr.length; i < len; i += 1) {
            buffer.push(numStr.substring(len - 1 - i, len - i));
            if (((i + 1) % 3 == 0) && (i != len - 1)) {
                buffer.push(sDelimeter);
            }
        }

        return buffer.reverse().join('').replace(",.", ".");
};

but now the sum field will not be shown neither when the page first load nor when doing a hard refresh for the web browser !!

  • 1
    Is the Minimal Download Strategy (MDS) feature activated on the site? – Dylan Cristy May 15 '17 at 12:39
  • @DylanCristy yes it is enabled for the current subsite.. and one thing i have corrected inside my original question.. now doing a column based filtering will update and show the sum column correctly.. but if i click on the list view name "All Items" the sum will disappear...or if i create a new item using the built-in create form and i am redirected to the "all items" view the sum field will not be shown.. – john Gu May 15 '17 at 12:58
  • 2
    its MDS, that is why i say to ALWAYS use Cisar, as it gives you the boilerplate code – Danny '365CSI' Engelman May 15 '17 at 14:06
  • @Danny'365CSI'Engelman my idea is that i am already aware of JSLINK, and it is used on many projects and it is one of the most recent and usful technologies in SP 2013... so i am trying to fix mycurrent jslink... this is the intention of my question... but i have no clue on how cisar works.. – john Gu May 15 '17 at 14:32
  • 1
    If manual work with CSR/JSlink is the horse and carriage, then Cisar is the Tesla.. both get you from A to B. It is the experience that differs. Cisar gives you half the CSR code you need, AND does all the JS file management and JSLinking for you – Danny '365CSI' Engelman May 15 '17 at 14:45
3

If MDS is enabled, you may need to take extra steps to ensure that your CSR script is recognized by the MDS system as something that needs to always run.

The MDS system has a function called RegisterModuleInit that has two parameters - a path to a script file, and the name of a function in that file that should always be run.

So in order to get the CSR script working with that, you have to change it from using an IIFE to having a named entry point function. This usually ends up looking something like this:

function myCSRRendering () {
    var myCtx = {};
    myCtx.Templates = {};
    myCtx.Templates.Fields = {
        "MyField": {
            "View": RenderMyField
        }
    };
    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(myCtx); 
};

function RenderMyField (ctx) {
    // do whatever you need for rendering in here
    return myOverrideHTML;
}

// register for MDS enabled sites
RegisterModuleInit('/path/to/my/CSR_Script.js', myCSRRendering);

// fallback for non-MDS enabled sites
myCSRRendering();

Here's a good blog post that talks about it in more detail.


To address your code edit - you have added the name of the function, but you still have it as an IIFE, which you need to remove.

What you have:

(function myFunctionName() {
    // you code here
})();

What you need to have:

function myFunctionName() {
    // you code here
};
  • thanks for the reply... now what i need to provide inside the "/path/to/my/CSR_Script.js" ?? should this reference the path for my JSLINK file? – john Gu May 15 '17 at 13:58
  • 2
    use Cisar It does half the work for you – Danny '365CSI' Engelman May 15 '17 at 14:10
  • 1
    sigh... Cisar does all the JSLinking for you.. – Danny '365CSI' Engelman May 15 '17 at 14:29
  • 1
    @johnG Yes, the path to use in RegisterModuleInit is the path to your JSLink file. – Dylan Cristy May 15 '17 at 15:17
  • 1
    @johnG addressed your code edit. – Dylan Cristy May 15 '17 at 15:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.