pepstock-org / Charba

J2CL and GWT Charts library based on CHART.JS
https://pepstock-org.github.io/Charba-Wiki/docs
Apache License 2.0
62 stars 6 forks source link

MeterChart null pointer error #104

Open AHijner opened 1 month ago

AHijner commented 1 month ago

Hi! We are trying to make a dashboard in our software using several meter-charts and bar-charts. However, we get a strange null-pointer exception. Specifically on line final double sideOfSquare = Math.floor((datasetMetaItem.getController().getInnerRadius() * 2) / SQRT_2); in the baseMeterController.execute(), it says the datasetMetaItem is null. With some debugging I find that one specific chart seems to not be initialized in the abstractChart.lookForConsistentInstance which results in the datasetMetaItem being null (note, a comment above this line states it can not be null so this is quite curious!). The specific chart that gives the error is the last meter-chart. A simplification of our layout would be: meter X | barchart Z meter Y | barchart Z In this case meterChart Y will give the null-pointer, meterChart X works alright. If I remove the barchart Z from the layout altogether, then meterChart Y will also work and there is no null-pointer exception. So it is a confusing situation I think! Below I will add our code, so hopefully you can replicate it.

ui.xml:

<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
    xmlns:g='urn:import:com.google.gwt.user.client.ui'
    xmlns:z='urn:import:nl.zermelo.online.app.widget'>

    <z:htmleventpanel.HTMLEventPanel ui:field="enrollmentPreregistrationDashboard" styleName="enrollmentPreregistrationDashboard">
        <div class="statusCharts">
            <g:SimplePanel ui:field="insufficientStatusChart" styleName="insufficientStatusChart"/>
            <g:SimplePanel ui:field="mediocreStatusChart" styleName="mediocreStatusChart"/>
        </div>
        <div class="rightSide">
            <g:SimplePanel ui:field="departmentChart" styleName="departmentChart"/>
        </div>
    </z:htmleventpanel.HTMLEventPanel>
</ui:UiBinder>

Java:

public class EnrollmentPreregistrationDashboardWidget extends Composite {

    interface MyUiBinder extends UiBinder<Panel, EnrollmentPreregistrationDashboardWidget> {}
    private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);

    @UiField HTMLPanel enrollmentPreregistrationDashboard;
    @UiField SimplePanel insufficientStatusChart;
    @UiField SimplePanel mediocreStatusChart;
    @UiField SimplePanel departmentChart;

    private MeterChartWidget insufficientStatusChartWidget;
    private MeterChartWidget mediocreStatusChartWidget;
    private StackedBarChartWidget departmentChartWidget;

    public EnrollmentPreregistrationDashboardWidget() {
        uiBinder.createAndBindUi(this);
        initWidget(enrollmentPreregistrationDashboard);
        Charba.enable();
        init();
    }

    private void init() {
        //MeterCharts
        insufficientStatusChartWidget = new MeterChartWidget();
        insufficientStatusChartWidget.getOptions().getTitle().setText("Onvoldoende");
        configureStatusChart(insufficientStatusChartWidget);
        insufficientStatusChart.add(insufficientStatusChartWidget);

        mediocreStatusChartWidget = new MeterChartWidget();
        mediocreStatusChartWidget.getOptions().getTitle().setText("Matig");
        configureStatusChart(mediocreStatusChartWidget);
        mediocreStatusChart.add(mediocreStatusChartWidget);

        //Department BarChart
        departmentChartWidget = new StackedBarChartWidget();
        departmentChartWidget.getOptions().getTitle().setText("Afdelingsoverzicht");

        StackedBarDataset insufficientDataset = departmentChartWidget.newDataset();
        insufficientDataset.setBackgroundColor("#E22D33");
        insufficientDataset.setStackGroup("main");
        insufficientDataset.setLabel("Onvoldoende");
        insufficientDataset.setDataPoints(new DataPoint("x", 5));
        departmentChartWidget.getData().setDatasets(insufficientDataset);

        departmentChart.add(departmentChartWidget);
    }

    private void configureStatusChart(MeterChartWidget statusChartWidget) {
        statusChartWidget.getOptions().getTitle().setDisplay(true);

        MeterDataset statusChartDataset = statusChartWidget.newDataset();
        statusChartDataset.getDescriptionLabel().setContent("Leerlingen");
        statusChartDataset.getDescriptionLabel().setDisplay(true);
        statusChartDataset.setMax(10);
        statusChartDataset.setValue(5);
        statusChartWidget.getData().setDatasets(statusChartDataset);
    }
}

We are using Charba 6.5-gwt and GWT 2.10.1

AHijner commented 1 month ago

Small update: we found some workaround. If we set the chart.isVisible(false) during initialization, and then after the container page has been fully loaded, we set chart.isVisible(true) the charts are drawn without error! It doesn't make too much sense to me yet, but it seems to work so far. And perhaps the info is useful for you as well.

stockiNail commented 1 month ago

uhm.. really strange. I haven't got time to investigate a bit. I'll do asap. The first think is related to the DOM observer, used to draw the chart. And in fact, setting the chart invisible could be the workaround.

I have never used UIBinder as you describe because I usually set the Chart directly in UIBinder (being the chart a SimplePanel).

AHijner commented 1 month ago

Alright no rush! Now we have this workaround we can keep developing our dashboard :)

stockiNail commented 1 month ago

Really appreciate you patience and that you are using Charba! ;) Thanks!