Extend List using JS Link with HighCharts
質問
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);
});
}
解決
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);
}