Skip to main content

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.

  1. Clear the content inside the renderChart function.
  2. Import ChartToTSEvent from ts-chart-sdk.
  3. Since we will be creating some custom options in using ChartToTSEvent.OpenContextMenu(sending post messages from chart to TS) in render with label Custom user action 1 and Download 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.
  1. Create a render(ctx:CustomChartContext) function which will deal with chart.js setup and using dataModel.Do the following steps to create a render 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;
}
}
  1. In renderChart we will be calling render function and integrating it some custom CharttoTSEvent 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);
}
};