Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding formatter to Donut/Pie Chart label causes JavaScript Error #92

Closed
Obi-TP opened this issue Dec 31, 2020 · 4 comments
Closed

Adding formatter to Donut/Pie Chart label causes JavaScript Error #92

Obi-TP opened this issue Dec 31, 2020 · 4 comments
Labels
bug Something isn't working

Comments

@Obi-TP
Copy link

Obi-TP commented Dec 31, 2020

Describe the bug
Adding a formatter via com.github.appreciated.apexcharts.config.plotoptions.pie.builder.ValueBuilder.withFormatter(String) causes JavaScript error "TypeError: (0 , t.value.formatter) is not a function".

Steps or code example to Reproduce
Sample Code:

private static Labels buildLabels() {		
	
	final String formatter = 	"function doSomeJavaScript(x) { " + 
						"    return x.toString().replace(/\\B(?=(\\d{3})+(?!\\d))/g, \",\");" + 
						"}";
	
	return LabelsBuilder.get()
						.withShow(true)
						.withName(NameBuilder	.get()
										.withColor(ColourCodes.BLACK)
										.withFontSize(LABEL_FONT_PX)
										.build())
						.withValue(ValueBuilder	.get()													
										.withFormatter(formatter)
										.build())
						.build();
}

Expected behavior
A formatted number should appear in the middle of the pie chart e.g. 1,000,000

Screenshots
image

@Obi-TP Obi-TP added the bug Something isn't working label Dec 31, 2020
@ILikePhysics
Copy link

ILikePhysics commented Feb 5, 2021

I have the same issue while trying to set a formatter on the total label of donut chart.
I am setting the following formatter:

function(w) {              
  w.globals.seriesTotals.reduce((a, b) => a + b, 0);               
} 

@mvysny
Copy link
Contributor

mvysny commented Apr 23, 2021

I think the problem here is that the Java wrapper sends the formatter value as a String while JavaScript side expects a function.

I don't think it's possible to send functions via JSON directly since JSON is not supposed to transfer functions: https://stackoverflow.com/questions/2001449/is-it-valid-to-define-functions-in-json-results

A workaround is needed: e.g. you'll need to attach the functions beforehand, say to the window object:

window.formatLabelTotal = function() { ... }

Then the wrapper code would accept the formatter Strings as function names, such as window.formatLabelTotal. However this needs to be implemented.

@ILikePhysics
Copy link

ILikePhysics commented Apr 23, 2021

I am able to set a formatter on other chart/label and it works.
For example, I do this

private val jvmMemoryChart = ApexChartsBuilder.get()
            .withChart(ChartBuilder.get()
                .withType(Type.bar)
                .build())
            .withPlotOptions(PlotOptionsBuilder.get()
                    .withBar(BarBuilder.get()
                            .withHorizontal(false)
                            .withColumnWidth("55%")
                            .build())
                    .build())
            .withTitle(TitleSubtitleBuilder.get().withText("JVM Memory").build())
            .withDataLabels(DataLabelsBuilder.get()
                    .withEnabled(true)
                    .withFormatter(jvmMemFormatterJsFucntion)
                    .build())
[...]

With this formatter string:

private val jvmMemFormatterJsFucntion =
          """
          function(val, {seriesIndex, dataPointIndex, w}) {              
              return (parseFloat(val).toFixed(2)) + " kB";               
          }    
          """.trimIndent()

When digging in the wrapper's JS code, this snippet must be the reason it works:

if (this.dataLabels) {
  this.config.dataLabels = JSON.parse(this.dataLabels);
  if (this.config.dataLabels.formatter) {
    this.config.dataLabels.formatter = this.evalFunction(this.config.dataLabels.formatter);
  }
}

The evalFunction() does the trick.

Also, by looking at the wrapper's JS code, I don't see anywhere that it handles the plotOptions Pie/Donut label configurations and evalutate the formatter's string. It is just not implemented for all types of label.

@mvysny
Copy link
Contributor

mvysny commented Apr 26, 2021

Excellent find! I can indeed see at apexcharts-wrapper.js:175 that the plotOptions formatter for pie/donut is not post-processed. Perhaps something like this should be in place:

if (this.plotOptions.pie && this.plotOptions.pie.donut && this.plotOptions.pie.donut.labels && this.plotOptions.pie.donut.labels.total && this.plotOptions.pie.donut.labels.total.formatter) {
  this.plotOptions.pie.donut.labels.total.formatter = this.evalFunction(this.plotOptions.pie.donut.labels.total.formatter);
}

(the same for this.plotOptions.pie.donut.labels.value).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants