09-Creating renderChart function
Pre-conditions
If you’ve followed the steps in the previous sections, you should have a copy of the code and be able to run it with an error on renderChart. If not, please revisit the previous lessons to get set up.
Implementing the renderChart
In this section we will be setting up renderChart
function with the chartModel context.
- Clear the content inside the
renderChart
function. - Import ChartToTSEvent from ts-chart-sdk.
- Since we will be creating some custom options in using
ChartToTSEvent.OpenContextMenu
(sending post messages from chart to TS) inrender
with labelCustom user action 1
andDownload chart
we need to create some function curresponding to that. Here are the snippet for that->
function getParsedEvent(evt: any) {
return _.pick(evt.native, ["clientX", "clientY"]); // create a object with clicked position to open context menu there.
}
function downloadChartAsPNG() {
const imageLink = document.createElement("a");
const canvas = document.getElementById("chart") as any;
imageLink.download = "bar-chart.png";
imageLink.href = canvas.toDataURL("image/png", 1);
imageLink.click();
} // that will be there in onClick.
- Note:
- For more info on
CharttoTSEvent
refer doc.
- For more info on
- Create a
render(ctx:CustomChartContext)
function which will deal withchart.js
setup and usingdataModel
.Do the following steps to create arender
function.
function render(ctx: CustomChartContext) {
const chartModel = ctx.getChartModel();
const dataModel = getDataModel(chartModel);
const allowLabels = _.get(chartModel.visualProps, visualPropKeyMap[2], false);
const labelColor = _.get(
chartModel.visualProps,
visualPropKeyMap[1],
availableColor[0]
);
if (!dataModel) {
return;
}
try {
const canvas = document.getElementById("chart") as any;
// clear canvas.
canvas.getContext("2d").clearRect(0, 0, canvas.width, canvas.height);
globalChartReference = new Chart(canvas as any, {
type: "bar",
data: {
labels: dataModel.getLabels(),
datasets: dataModel.getDatasets() as any,
},
options: {
animation: {
duration: 0,
},
scales: dataModel.getScales(),
plugins: {
// Change options for ALL labels of THIS CHART
datalabels: {
display: allowLabels,
color: labelColor,
labels: {
title: {
font: {
weight: "bold",
},
},
value: {
color: "black",
},
},
},
},
// responsive: true,
maintainAspectRatio: false,
interaction: {
mode: "point",
intersect: true,
},
onClick: (e: any) => {
const activeElement = e.chart.getActiveElements()[0];
const dataX = activeElement.index;
const dataY = activeElement.datasetIndex;
ctx.emitEvent(ChartToTSEvent.OpenContextMenu, {
event: getParsedEvent(e),
clickedPoint: {
tuple: dataModel.getPointDetails(dataX, dataY),
},
customActions: [
{
id: "custom-action-1",
label: "Custom user action 1",
icon: "",
onClick: (...arg) => {
console.log("custom action 1 triggered", arg);
},
},
{
id: "download-chart",
label: "Download chart",
icon: "",
onClick: () => {
downloadChartAsPNG();
},
},
],
});
},
},
plugins: [
createPlotlinePlugin(dataModel), // Add the custom plotline plugin
createPlotbandPlugin(dataModel), // Add the custom plotband plugin
],
});
} catch (e) {
console.error("renderfailed", e);
throw e;
}
}
- In
renderChart
we will be calling render function and integrating it some customCharttoTSEvent
that will help in notifying ThoughtSpot different rendering stages. Copy the snippet below to implement it:
NOTE: For more information about the ChartToTSEvents component, refer to the following documentation resources:
const renderChart = async (ctx: CustomChartContext): Promise<void> => {
try {
ctx.emitEvent(ChartToTSEvent.RenderStart);
render(ctx);
} catch (e) {
ctx.emitEvent(ChartToTSEvent.RenderError, {
hasError: true,
error: e,
});
} finally {
ctx.emitEvent(ChartToTSEvent.RenderComplete);
}
};