0

In a list view I want to override a value with a small chart with HighCharts...

The Basic idea: Render the highchart into the jquery container and then return the HTML code:

    (function(){
    var Resports = {};

    Resports.Templates = {
        Fields: {
            "Report": { "View": pieChart },
        }
    };
    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(Resports);

})();

function pieChart(ctxOBJ) {
    valueSTR = ctxOBJ.CurrentItem[ctxOBJ.CurrentFieldSchema.Name];

    chartsConfigJSON = {
            chart: {
                type: 'bar'
            },
            title: {
                text: 'Fruit Consumption'
            },
            yAxis: {
                title: {
                    text: 'Fruit eaten'
                }
            },
            series: [{
                name: 'Jane',
                data: [valueSTR]
            }, {
                name: 'John',
                data: [5]
            }]
        }
    containerOBJ = $('<div>');
    containerOBJ.highcharts(chartsConfigJSON);

    return containerOBJ();
}

But high charts just renders the empty diagram without the actual bars.

I guess that it needs an existing container that is already attached to the DOM tree, because it wants to animate the bars in real time.

Is there a way to force highcharts to use a JQuery object that is not attached to the DOM?

thx -Dave

Here is an update (does not work on a grouped view, where it just rederes the last group in the list):

(function(){

    var Reports = {};
    Reports.Templates = {
        Fields: {
            "OEE": { "View": preRenderValue },
            "Yield": { "View": preRenderValue },
            "Availabilty": { "View": preRenderValue },
            "Performance": { "View": preRenderValue },
        }
    };

    Reports.OnPostRender = pieChart;
    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(Reports);
})();

function preRenderValue(ctxOBJ) {
    valueSTR = ctxOBJ.CurrentItem[ctxOBJ.CurrentFieldSchema.Name];
    containerJQR = $('<div class="chartContainer" style="width:40px; height:40px">');
    containerJQR.text(valueSTR);
    //idINT = ctxOBJ.CurrentItem.Id;
    return containerJQR.prop('outerHTML');
}

function pieChart(ctxOBJ) {
    //ctxOBJ.CurrentItem;

    $('.chartContainer').each(function(){       
        var valueFLT = $(this).text() * 100;
        var invertFLT = (100 - valueFLT);
        //console.log($(this).text() + ": " + valueFLT + '|' + invertFLT);

        //chartsDataJSN = [valueFLT, invertFLT];
        chartsConfigJSON.colors = ['#' + getColor(valueFLT), '#F5F5F5'];
        chartsConfigJSON.series = [{
            data: [valueFLT, invertFLT],
        }];

        $(this).highcharts(chartsConfigJSON);
    });
}
1

I don't think you can force Highcharts to use something that is not already attached to the DOM, but what you can do is use the rendering cycle to set yourself up a placeholder in the DOM, and then put off using Highcharts until the DOM is ready by calling it from OnPostRender.

Something like:

// set up a place to store data that can be accesed 
// from various different function scopes
var MyNameSpace = MyNameSpace || {};

(function () {
    var Resports = {};

    Resports.Templates = {
        Fields: {
            "Report": { "View": setUpDiv },
        }
    };
    Resports.OnPostRender = pieChart;
    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(Resports);

})();

function setUpDiv (ctxOBJ) {
    // store whatever data we will need later
    MyNameSpace.DataINeedLater = ctxOBJ.CurrentItem[ctxOBJ.CurrentFieldSchema.Name];

    // set up a placeholder to use later
    return '<div id="chartHolder"></div>';
}

// this is now called from OnPostRender
// so the DOM will be available
function pieChart() {

    chartsConfigJSON = {
        chart: {
            type: 'bar'
        },
        title: {
            text: 'Fruit Consumption'
        },
        yAxis: {
            title: {
                text: 'Fruit eaten'
            }
        },
        series: [{
            name: 'Jane',
            data: [MyNameSpace.DataINeedLater]
        }, {
            name: 'John',
            data: [5]
        }]
    }

    containerOBJ = $('div#chartHolder');
    containerOBJ.highcharts(chartsConfigJSON);
}
  • I tried that already... the problem is, that the postRender function will be called severall time when using a grouped view and then it only renders one of the charts... But probably the only possible way... – Dave Apr 6 '18 at 13:55
  • Oh I got it... had to remove the CSS class, to prevent JQuery to overwrite the already rendered containers... – Dave Apr 6 '18 at 14:22

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.