Vaadin chart XAxis setMax does not work in combined chart

Hello experts,
I have a specification that need to combine and show spline chart and column chart, and the spline line needs to reach the end/right border of the chart. But I’m unable to achieve that even when I set a DataSeriesItem at max date value of XAxis. This only happens in combination of spline chart and column chart. If it is a standalone spline chart, everything is showing correctly. Am I missing any configuration ?

I created a sample of Vaadin 23 and 24, and got same problem

public class SplineView extends VerticalLayout {
    public SplineView() {
        Chart chart = new Chart(ChartType.SPLINE);
        chart.setTimeline(true);
        Configuration configuration = chart.getConfiguration();
        configuration.getTitle().setText("AAPL Stock Price");
        configuration.getTooltip().setEnabled(true);
        XAxis xAxis = configuration.getxAxis();
        xAxis.setType(AxisType.DATETIME);
        xAxis.setTickWidth(2);
        xAxis.setOrdinal(false);
        xAxis.setMax(Date.from(Instant.now()));

        YAxis columnYAxis = new YAxis();
        columnYAxis.setShowEmpty(false);
        columnYAxis.setVisible(false);
        configuration.addyAxis(columnYAxis);
        DataSeries dataSeries = new DataSeries();
        Random random = new Random();
        Map<Integer, DataSeries> multipleDataSeries = new HashMap();
        var stockPrices = StockPrices.fetchAaplPrice();

        for (var stock  : stockPrices) {
            StockPrices.PriceData data = (StockPrices.PriceData)stock.next();
            DataSeriesItem item = new DataSeriesItem();
            item.setX(Instant.ofEpochMilli(data.getDate()).plus(2920L, ChronoUnit.DAYS));
            item.setY(data.getPrice());
            dataSeries.add(item);
            Integer randomNumber = random.nextInt();
            DataSeries columnDataSeries;
            if (multipleDataSeries.containsKey(randomNumber)) {
                columnDataSeries = multipleDataSeries.get(randomNumber);
            } else {
                columnDataSeries = new DataSeries();
                PlotOptionsColumn plotOptionsColumn = new PlotOptionsColumn();
                plotOptionsColumn.setPointWidth(30);
                columnDataSeries.setPlotOptions(plotOptionsColumn);
                multipleDataSeries.put(randomNumber, columnDataSeries);
            }

            if (random.nextInt(100) < 10) {
                DataSeriesItem columnItem = new DataSeriesItem();
                columnItem.setX(Instant.ofEpochMilli(data.getDate()).plus(2920L, ChronoUnit.DAYS));
                columnItem.setY(data.getPrice());
                columnDataSeries.add(columnItem);
            }
        }

        DataSeriesItem nowItem = new DataSeriesItem();
        nowItem.setX(Instant.now());
        nowItem.setY(120);
        dataSeries.add(nowItem);
        configuration.addSeries(dataSeries);
        multipleDataSeries.values().forEach((s) -> {
            configuration.addSeries(s);
        });
        RangeSelector rangeSelector = new RangeSelector();
        rangeSelector.setSelected(1);
        configuration.setRangeSelector(rangeSelector);
        this.add(new Component[]{chart});
    }
}

Here is what it looks like

I solved this by adding this:

plotOptionsColumn.setPointPlacement(PointPlacement.ON);

after plotOptionsColumn = new PlotOptionsColumn();

Also you probably want to change this.add(new Component[]{chart}); to add(chart);

1 Like

Hi Herberts,
Thank you for helping on the issue. I added PointPlacement.ON to my chart, but it does not really solve the issue. If I set the Range selector to Day view, the last point still did not reach the end of the graph. One additional abnormal issue that I noticed is: if I drag and drop to change the date, the last point will reach the end and I can not drag to the future, but if I use the right scroll bar button, I still can extend the chart to few hours ahead last point. Do you think it is a bug ?

Sorry for not mentioned ealier that my main view is Day view. Here is the code that I updated

public class SplineView extends VerticalLayout implements IView {
    public SplineView() {
        Chart chart = new Chart(ChartType.SPLINE);
        chart.setTimeline(true);
        Configuration configuration = chart.getConfiguration();
        configuration.getTitle().setText("AAPL Stock Price");
        configuration.getTooltip().setEnabled(true);

        XAxis xAxis = configuration.getxAxis();
        xAxis.setType(AxisType.DATETIME);
        xAxis.setTickWidth(2);
        xAxis.setOrdinal(false);
        xAxis.setMax(Date.from(Instant.now()));

        YAxis columnYAxis = new YAxis();
        columnYAxis.setShowEmpty(false);
        columnYAxis.setVisible(false);
        configuration.addyAxis(columnYAxis);
        DataSeries dataSeries = new DataSeries();
        Random random = new Random();
        Map<Integer, DataSeries> multipleDataSeries = new HashMap();
        var fullStockPrices = StockPrices.fetchAaplPrice();
        var stockPrices = fullStockPrices.subList((fullStockPrices.size()/3)*2, fullStockPrices.size()-1);

        for (var stock  : stockPrices) {
            DataSeriesItem item = new DataSeriesItem();
            item.setX(Instant.ofEpochMilli(stock.getDate()).plus(2920L, ChronoUnit.DAYS));
            item.setY(stock.getPrice());
            dataSeries.add(item);
            Integer randomNumber = random.nextInt();
            DataSeries columnDataSeries;
            if (multipleDataSeries.containsKey(randomNumber)) {
                columnDataSeries = multipleDataSeries.get(randomNumber);
            } else {
                columnDataSeries = new DataSeries();
                PlotOptionsColumn plotOptionsColumn = new PlotOptionsColumn();
                plotOptionsColumn.setPointPlacement(PointPlacement.ON);
                plotOptionsColumn.setPointRange(30);
                plotOptionsColumn.setPointWidth(30);
                columnDataSeries.setPlotOptions(plotOptionsColumn);
                multipleDataSeries.put(randomNumber, columnDataSeries);
            }

            if (random.nextInt(100) < 10) {
                DataSeriesItem columnItem = new DataSeriesItem();
                columnItem.setX(Instant.ofEpochMilli(stock.getDate()).plus(2920L, ChronoUnit.DAYS));
                columnItem.setY(stock.getPrice());
                columnDataSeries.add(columnItem);
            }
        }

        DataSeriesItem nowItem = new DataSeriesItem();
        nowItem.setX(Instant.now());
        nowItem.setY(120);
        dataSeries.add(nowItem);

        configuration.addSeries(dataSeries);
        multipleDataSeries.values().forEach((s) -> {
            configuration.addSeries(s);
        });
        RangeSelector rangeSelector = new RangeSelector();
        final RangeSelectorButton btnDay = new RangeSelectorButton(RangeSelectorTimespan.DAY, 1, "Day");
        final RangeSelectorButton btnWeek = new RangeSelectorButton(RangeSelectorTimespan.WEEK, 1, "Week");
        rangeSelector.setEnabled(true);
        rangeSelector.setButtons(btnWeek, btnDay);
        rangeSelector.setSelected(1);
        configuration.setRangeSelector(rangeSelector);
        this.add(chart);
    }

}

I suspect there is some timezone conflict going on here.
If I add +2 hours to the ‘nowItem’, which is equivalent to my timezone (UTC+2), it does seem to go to the edge of the chart.

DataSeriesItem nowItem = new DataSeriesItem();
nowItem.setX(Instant.now().plus(2, ChronoUnit.HOURS));

Not completely sure how to work around this, but I think it might be enough for you to just remove the xAxis.setMax(..) to fit your use-case.

Thank you Herberts,
With additional timezone adjustment, your solution work perfectly on my chart view.