Vaadin 14: deal with Negative values in Pie Charts

Hello everyone,

I am trying to deal with Negative values on PieCharts.
Is there a proper way to do it?

Currently, I made another series with negative values rendered positive.
It works but I want Legend to display the real, negative, value.

Does anyone have a clue about this?

From highcharts documentation it seems that there’s a “negative” attribute that can be used. If you set the series item as negative then you can use that to format the legend. In order to use it you can extend DataSeriesItem to add this attribute. And then you can use it as in the following example:

public PieChartView() {
    Chart chart = new Chart(ChartType.PIE);

    Configuration conf = chart.getConfiguration();

    Tooltip tooltip = new Tooltip();
    tooltip.setValueDecimals(1);
    conf.setTooltip(tooltip);

    PlotOptionsPie plotOptions = new PlotOptionsPie();
    plotOptions.setAllowPointSelect(true);
    plotOptions.setCursor(Cursor.POINTER);
    plotOptions.setShowInLegend(true);
    conf.setPlotOptions(plotOptions);

    DataSeries series = new DataSeries();
    series.add(new DataSeriesItem("Item 10", 61.41));
    series.add(new DataSeriesItem("Item 11", 11.84));
    series.add(new DataSeriesItem("Item 12", 10.85));
    series.add(new DataSeriesItem("Item 13", 4.67));
    series.add(new DataSeriesItem("Item 14", 4.18));
    series.add(new DataSeriesItem("Item 15", 1.64));
    series.add(new DataSeriesItem("Item 16", 6.2));
    series.add(new DataSeriesItem("Item 17", 1.2));
    CustomDataSeriesItem item18DataSeriesItem = new CustomDataSeriesItem("Item 18", 2.61);
    item18DataSeriesItem.setNegative(true);
    series.add(item18DataSeriesItem);
    conf.setSeries(series);
   
    // LEGEND
    conf.getLegend().setLabelFormatter("function() {return this.negative ? -this.y : this.y; }");
    
    // TOOLTIP
    conf.getTooltip().setFormatter(
            "function() { var value = this.point.negative ? -this.y : this.y; return '<b>'+ this.point.name +'</b><br/>'+this.series.name +': '+ value }");

    add(chart);
}

public class CustomDataSeriesItem extends DataSeriesItem {

    private boolean negative = false;

    public CustomDataSeriesItem(String name, Number y) {
        super(name, y);
    }

    public void setNegative(boolean negative) {
        this.negative = negative;
    }

    public boolean getNegative() {
        return this.negative;
    }
}
2 Likes

Hello Paola!

Thank you for your answer.
I dealt with Legend labelFormatter and it worked :+1:

For other readers: I had to split positive and negative values into 2 series to display them according to my needs. I also made a donut with the positive series and another inside with the negative series.

final DataSeries dataSeries = new DataSeries();
final DataSeries negativeAsPositiveDataSeries = new DataSeries();

final PlotOptionsPie plotOptionsPie = new PlotOptionsPie();
plotOptionsPie.setInnerSize("60%");
dataSeries.setPlotOptions(plotOptionsPie); 

final PlotOptionsPie negativeAsPositivePlotOptionsPie = new PlotOptionsPie();
negativeAsPositivePlotOptionsPie.setInnerSize("50%");
negativeAsPositivePlotOptionsPie.setSize("50%");
negativeAsPositiveDataSeries.setPlotOptions(negativeAsPositivePlotOptionsPie);

chart.getConfiguration().addSeries(dataSeries , negativeAsPositiveDataSeries);
1 Like