I created a stacked line chart with echarts and I used the built-in transform to filter the provided data and ecSimpleTransform to aggregate the values. However, after filtering some datasets become empty, because none of their values match the filter condition. I would like to add a legend, but it also includes labels for the empty datasets. Is there a way to filter the legend values as well?
I attached a simplified version of the chart config.
I also created a CodeSandbox example.
legendData= [...] //list of possible 'propertyOne' values
const chartConfig = {
dataset: [
{
id: 'raw',
dimensions: ['date', 'value', 'propertyOne', 'propertyTwo'],
source: values,
},
{
id: 'filtered',
fromDatasetId: 'raw',
transform: [
{
type: 'filter',
config: {
dimension: 'propertyTwo',
'=': 'providedValue',
},
},
],
},
...legendData.map(propertyOneValue=> {
return {
id: propertyOneValue,
fromDatasetId: 'filtered',
transform: [
{
type: 'filter',
config: {
dimension: 'propertyOne',
'=': propertyOneValue,
},
},
{
type: 'ecSimpleTransform:aggregate',
config: {
resultDimensions: [
{ name: 'propertyOne', from: 'propertyOne' },
{ name: 'sum', from: 'value', method: 'sum' },
{ name: 'date', from: 'date' },
],
groupBy: 'date',
},
},
],
};
}),
],
tooltip: {
trigger: 'axis',
confine: true,
},
yAxis: {
nameLocation: 'middle',
nameGap: 30,
scale: true,
},
xAxis: {
type: 'category',
position: 'top',
},
grid: {
bottom: 50,
containLabel: true,
},
legend: {
selected: { detail: false },
data: legendData,
bottom: 0,
type: 'scroll',
},
series: [
...legendData.map(propertyOneValue => {
return {
name: propertyOneValue ,
type: 'line' as 'line',
areaStyle: {},
datasetId: propertyOneValue,
stack: 'Total',
encode: {
x: 'date',
y: 'sum',
itemName: 'propertyOne',
tooltip: 'sum',
},
};
}),
],
}
The chart's legend is going to display as many values as there are in legend.data
. In your example, legendData
still has 4 values when you assign it to legend.data
instead of just being ["custom 1", "custom 2"].
One simple way of doing it would be to only add what you want in legend.data
when you create it (instead of filtering legendData later).
values.forEach((value) => {
//just addind a second condition when pushing values to legendData
if (!legendData.includes(value.propertyOne) && value.propertyTwo == "providedValue"){
legendData.push(value.propertyOne);
}
});
I don't know exactly what you intend to do with this application, but this solution works on the sandbox you provided. Even later when you do ...legendData.map()
, you won't get poluted with useless values (from custom 3 & 4).