08-Creating dataModel from Input data
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.
Create a Data Model from input data
The data model is unique to every chart. It defines how each point will be plotted on the chart. In this step we will deal with thoughtspot ChartModel to create dataModel and feed that dataModel to to new Charts
in render
function that we will be create in next step in chart.js
required format.
Let's create dataModel with the following steps:
- Create the function
getDataModel
that will takechartModel
and returncolumnchartModel
object. Code snippet is as follow-
function getDataModel(
chartModel: ChartModel,
customStyleConfig: ChartSdkCustomStylingConfig | undefined
) {
// column chart model
const columnChartModel = getColumnDataModel(
chartModel.config?.chartConfig?.[0].dimensions ?? [],
chartModel.data?.[0].data ?? [],
"bar",
chartModel.visualProps,
customStyleConfig
);
return columnChartModel;
}
- Create two global array that will have with name
availableColor
andvisualPropKeyMap
that will be used to provide default color configurations and mapping key value pair that we will be getting from invisualProp
. The code snippet is as follow-
Chart.register(ChartDataLabels);
let globalChartReference: Chart;
const availableColor = ["red", "green", "blue"];
const visualPropKeyMap = {
0: "color",
1: "accordion.Color2",
2: "accordion.datalabels",
};
- In this we will be implementing
getColumnDataModel
that is there ingetDataModel
. This willchartConfig
,chartData
(data),type
andvisualprop
(current prop key and value) and return object with function such asgetLabel
,getDatasets
(axisId,type,colorConfiguration),getScales
(chart.js display configurations) andgetPointDetails
. Code snippet is given below-
function getColumnDataModel(
configDimensions,
dataArr: DataPointsArray,
type,
visualProps: VisualProps
) {
// this should be handled in a better way
const xAxisColumns = configDimensions?.[0].columns ?? [];
const yAxisColumns = configDimensions?.[1].columns ?? [];
return {
getLabels: () => getDataForColumn(xAxisColumns[0], dataArr),
getDatasets: () =>
_.map(yAxisColumns, (col, idx) => {
const coldata = getDataForColumn(col, dataArr);
const CFforColumn = getCfForColumn(col);
const axisId = `${type}-y${idx.toString()}`;
const color = coldata.map((value, index) =>
getBackgroundColor(
customStyleConfig,
visualProps,
idx,
dataArr,
CFforColumn,
index,
col.id
)
);
return {
label: col.name,
data: coldata,
yAxisID: axisId,
type: `${type}`,
backgroundColor: color,
borderColor: color,
datalabels: {
anchor: "end",
},
};
}),
getScales: () =>
_.reduce(
yAxisColumns,
(obj: any, _val, idx: number) => {
// eslint-disable-next-line no-param-reassign
obj[`${type}-y${idx.toString()}`] = {
grid: {
display: true,
},
position: idx === 0 ? "left" : "right",
title: {
display: true,
text: _val.name,
},
};
return obj;
},
{}
),
getPointDetails: (xPos: number, yPos: number): PointVal[] => [
{
columnId: xAxisColumns[0].id,
value: getDataForColumn(xAxisColumns[0], dataArr)[xPos],
},
{
columnId: yAxisColumns[yPos].id,
value: getDataForColumn(yAxisColumns[yPos], dataArr)[xPos],
},
],
};
}
- In the above implementation you will be getting error inside
getPointsdetails
beacuse we have a undefined functiongetDataForColumn
. This function will take the column ids and return the specific cloumn data. Implement this function in with the following code snippet->
function getDataForColumn(column: ChartColumn, dataArr: DataPointsArray) {
const idx = _.findIndex(dataArr.columns, (colId) => column.id === colId);
return _.map(dataArr.dataValue, (row) => row[idx]);
}
-
In the above implementation, you will need to implement the following functions to ensure that the conditional formatting and background colors are correctly applied, and that the plotlines and plotbands are drawn on the chart.
getBackgroundColor
: This function determines the background color for each data point based on custom style configurations, visual properties, and any applicable conditional formatting rules. Implement this function with the following code snippet:export function getBackgroundColor(
customStyleConfig: ChartSdkCustomStylingConfig,
visualProps: VisualProps,
idx: any,
dataArr: any,
CFforColumn: any,
index: number,
colId: any
) {
const color =
customStyleConfig?.chartColorPalettes?.length &&
customStyleConfig?.chartColorPalettes[0].colors.length > 0
? customStyleConfig?.chartColorPalettes[0].colors
: _.get(visualProps, visualPropKeyMap?.[idx], availableColor[idx]);
return color;
}