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

Setting beginAtZero #24

Closed ak80 closed 5 years ago

ak80 commented 5 years ago

Hi,

thanks for all the effort you put in Charba, we just started using it and I alreay like it!

I am trying to get a Y axis to start from zero. The chartjs way seems to be to set a flag beginAtZero on the ticks to true.

I tried this:

      CartesianLinearAxis axis = new CartesianLinearAxis(chart);
      axis.getTicks().setBeginAtZero(true);
      chart.getOptions().getScales().setYAxes(axis);

But I get an exception at runtime:

ConsoleLogger.java:33 Uncaught exception: (TypeError) : this.$init_12554_g$ is not a function
log_33_g$ @ ConsoleLogger.java:33
ConsoleLogger.java:33     at Unknown.JavaScriptObjectContainer_2_g$(MyClient-0.js@8:338027)
    at Unknown.JavaScriptObjectContainer_1_g$(MyClient-0.js@34:338021)
    at Unknown.ChartContainer_1_g$(MyClient-0.js@34:340006)
    at Unknown.BaseTick_1_g$(MyClient-0.js@23:349429)
    at Unknown.Tick_1_g$(MyClient-0.js@17:350247)
    at Unknown.CartesianTick_1_g$(MyClient-0.js@13:349669)
    at Unknown.new CartesianLinearTick_1_g$(MyClient-0.js@22:349742)
    at Unknown.CartesianLinearAxis_2_g$(MyClient-0.js@45:349651)
    at Unknown.new CartesianLinearAxis_1_g$(MyClient-0.js@28:349646)
    at Unknown.lambda$0_545_g$(MyClient-0.js@17:207978)
    at Unknown.execute_135_g$(MyClient-0.js@3:208127)
    at Unknown.$executeScheduled_0_g$(MyClient-0.js@40:15033)
    at Unknown.runScheduledTasks_0_g$(MyClient-0.js@9:14755)
    at Unknown.flushPostEventPumpCommands_0_g$(MyClient-0.js@5:14847)
    at Unknown.execute_5_g$(MyClient-0.js@22:14986)
    at Unknown.execute_4_g$(MyClient-0.js@19:14723)
    at Unknown.apply_23_g$(MyClient-0.js@28:14409)
    at Unknown.entry0_0_g$(MyClient-0.js@16:14465)
    at Unknown.anonymous(MyClient-0.js@14:14445)
    at Unknown.callback_0_g$(MyClient-0.js@45:14774)

Is there a precondition that I missed? Or is there even a better way to get an axis to start at zero

stockiNail commented 5 years ago

@ak80 Thank you very much! We are doing our best!

About the issue, you are using version 1.7, isn't it?

We have done a test, using setBeginAtZero, this is the code that we have created:

chart.getOptions().setResponsive(true);
chart.getOptions().setMaintainAspectRatio(true);
chart.getOptions().setAspectRatio(3);
chart.getOptions().getLegend().setPosition(Position.top);
chart.getOptions().getTitle().setDisplay(true);
chart.getOptions().getTitle().setText("Charba Line Chart");
chart.getOptions().getTooltips().setMode(InteractionMode.index);
chart.getOptions().getTooltips().setIntersect(false);
chart.getOptions().getHover().setMode(InteractionMode.nearest);
chart.getOptions().getHover().setIntersect(true);

LineDataset dataset1 = chart.newDataset();
dataset1.setLabel("dataset 1");

IsColor color1 = Colors.ALL[0];

dataset1.setBackgroundColor(color1.toHex());
dataset1.setBorderColor(color1.toHex());
double[] values = getRandomDigits(months, false);
dataset1.setData(values);
dataset1.setFill(Fill.nofill);
LineDataset dataset2 = chart.newDataset();
dataset2.setLabel("dataset 2");

IsColor color2 = Colors.ALL[1];

dataset2.setBackgroundColor(color2.toHex());
dataset2.setBorderColor(color2.toHex());
dataset2.setData(getRandomDigits(months, false));
dataset2.setFill(Fill.nofill);
dataset2.setHidden(false);

CartesianCategoryAxis axis1 = new CartesianCategoryAxis(chart);
axis1.setDisplay(true);
axis1.getScaleLabel().setDisplay(true);
axis1.getScaleLabel().setLabelString("Month");

CartesianLinearAxis axis2 = new CartesianLinearAxis(chart);
axis2.setDisplay(true);
axis2.getTicks().setBeginAtZero(true);
axis2.getScaleLabel().setDisplay(true);
axis2.getScaleLabel().setLabelString("Value");

chart.getOptions().getScales().setXAxes(axis1);
chart.getOptions().getScales().setYAxes(axis2);

chart.getData().setLabels(getLabels());
chart.getData().setDatasets(dataset1, dataset2);

Here is the result, without any exception:

zero

Could you put here the complete code in order to recreate the use case?

ak80 commented 5 years ago

Thanks for your quick response. Yes I am using Charba 1.7.

I tried with your code sample, and it is not working, so the problem must lie outside. Note that we create the Chart object with new and then configure it, set all the data and after that put it in a panel to be displayed. Could this be the issue.

For completeness here our code

    LineChart chart = new LineChart();
    chart.setWidth("100%");
    chart.getOptions().getLayout().getPadding().setTop(16);
    chart.getOptions().getLayout().getPadding().setBottom(32);

    chart.getOptions().setResponsive(true);
    chart.getOptions().setMaintainAspectRatio(false);
    chart.getOptions().getLegend().setDisplay(true);

    LineDataset dataSet = chart.newDataset();
    dataSet.setBackgroundColor("#4863A0");
    dataSet.setData(new double[]{90.0, 80.0, 88.0});
    chart.getData().setDatasets(dataSet);
    chart.getData().setLabels("one", "two", "three");

    CartesianLinearAxis axis = new CartesianLinearAxis(chart);
    axis.setDisplay(true);
    axis.getTicks().setBeginAtZero(true);
    axis.getScaleLabel().setDisplay(true);
    axis.getScaleLabel().setLabelString("Value");

    chart.getOptions().getScales().setXAxes(axis);
stockiNail commented 5 years ago

@ak80 Well, I have tried your code as following (in your code you use setXAxes but I think you wanted setYAxes):

@UiField
VerticalPanel panel;

public LineView() {
    initWidget(uiBinder.createAndBindUi(this));

    LineChart chart = new LineChart();
    chart = new LineChart();
    chart.setWidth("100%");
    chart.getOptions().getLayout().getPadding().setTop(16);
    chart.getOptions().getLayout().getPadding().setBottom(32);
    chart.getOptions().setResponsive(true);
    chart.getOptions().setMaintainAspectRatio(false);
    chart.getOptions().getLegend().setDisplay(true);

    LineDataset dataSet = chart.newDataset();
    dataSet.setBackgroundColor("#4863A0");
    dataSet.setData(new double[] { 90.0, 80.0, 88.0 });
    chart.getData().setDatasets(dataSet);
    chart.getData().setLabels("one", "two", "three");

    CartesianLinearAxis axis = new CartesianLinearAxis(chart);
    axis.setDisplay(true);
    axis.getTicks().setBeginAtZero(true);
    axis.getScaleLabel().setDisplay(true);
    axis.getScaleLabel().setLabelString("Value");
    chart.getOptions().getScales().setYAxes(axis);

    panel.add(chart);

}

In UI binder:

<!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:c="urn:import:org.pepstock.charba.client">

    <g:HTMLPanel  width="100%">
       <g:VerticalPanel ui:field="panel" width="100%" height="100%" >
       </g:VerticalPanel>
    </g:HTMLPanel>
</ui:UiBinder> 

and it works.

I've done also another test, creating the chart but to not add to panel in panel constructor. I've added a button to add the chart and it works as well.

zero1

Then, I went to the row of code where you got the exception and it sounds correct (is the base for all Charba objects in version 1.7).

Interesting issue....

Are you using GWT 2.8.2?

Do you have more details about MyClient part?

ak80 commented 5 years ago

@stockiNail Yes it is GWT 2.8.2, Java 8.

The application is quite big, maybe I can try to isolate the code and see when it breaks. I am not sure what I can tell you that would be interesting. We use gin/guice and separate our pages into presenter and view. In this case we a have a presenter for charts that determines which type should be displayed (by an enum) and then generates the line chart. Originally it was injected and the data for the series and labels came from a rest call that was done before creating the line chart. But I changed that to be static information. Also I tried adding the chart to an existing panel before rendering it but got some weird exceptions... so I am doing a clean build now. Maybe something in devmode got stuck - it wouldn't be the first time that happened to me.

stockiNail commented 5 years ago

@ak80 Let me know. FYI, we are using Charba in an application based on GWT Material (where gin is used), version 1.7, and we don't have any issue. I'd ask you if the issue is isolated to setBeginAtZero on ticks and then, removing it, you still get the issue. I don't think so. I'm still investigating to catch the exception. I see you are also using deferred command and I'm gonna try it as well.

ak80 commented 5 years ago

@stockiNail: well what do you know... I rebuild the code based on your sample. Did a clean build and threw away all the leftofvers in my temp folder (gwt caches / codeserver leftovers) and now it works. I am not sure what went wrong but maybe with some of the lambdas and callbacks in the code something got stuck.

Let me thank you again for such quick and helpful response. I am sorry it seems like I messed it up somehow. Anyway I am very happy with the outcome.

For comepleteness sake, here s the code I use now

  private RenderedReport renderLineChart(Report report) {
    LineChart chart = injector.getLineChart();

    chart.setWidth("100%");
    chart.getOptions().getLayout().getPadding().setTop(16);
    chart.getOptions().getLayout().getPadding().setBottom(32);

    chart.getOptions().setResponsive(true);
    chart.getOptions().setMaintainAspectRatio(false);
    chart.getOptions().getLegend().setDisplay(false);
    LineDataset dataSet = chart.newDataset();
    dataSet.setBackgroundColor(getColor(0, 1));
    dataSet.setData(report.getSeries(0));
    dataSet.setFill(Fill.nofill);

    CartesianCategoryAxis axis1 = new CartesianCategoryAxis(chart);
    axis1.setDisplay(true);
    axis1.getScaleLabel().setDisplay(true);
    axis1.getScaleLabel().setLabelString(report.getLabelAxisY());
    chart.getOptions().getScales().setXAxes(axis1);

    CartesianLinearAxis axis2 = new CartesianLinearAxis(chart);
    axis2.setDisplay(true);
    axis2.getTicks().setBeginAtZero(!report.isBestFit());
    axis2.getScaleLabel().setDisplay(true);
    axis2.getScaleLabel().setLabelString(report.getLabelAxisX());

    chart.getOptions().getScales().setYAxes(axis2);

    chart.getData().setLabels(report.getLabels());
    chart.getData().setDatasets(dataSet);

   // this is basically just a wrapper. The callse will pass it to the view 
   // which will get the chart out of it and put it into a panel
    return new RenderedReport(chart);
  }
stockiNail commented 5 years ago

@ak80 I'm very happy too! Thank you! Please start having a look to version 2.0, if you can. Some bugs/features are fixed over there!