I simplified my code to show the problem as easy as I could. Here is part of my code that I use to create my HighCharts:
$('#myChart').highcharts('StockChart', {
chart: {
events: {
load: function () {
// Here I have length 3, but it should be 2
for (i = 0; i < this.series.length; i++)
...
},
},
},
...
...
// returnVal is a valid object with length 2
series: returnVal;
});
returnVal is a proper object, which has 2 data series inside (its length is 2). Something like this:
{
dataGrouping: {
enabled: true,
},
yAxis: 0,
validData
},
{
dataGrouping: {
enabled: true,
},
yAxis: 1,
validData
},
However, when the load: method is executed, this.series.length is 3 (there is additional series inside).
This is how the last series looks like in the debugger (data array is empty):
Is this only my case? What can be the cause?
Related
I'm a beginner in Vue and I'm using vue-apex chart to create a chart in my application. I want to display in chart, the values of the two component's properties "uncorrectAns" and "correctAns" that I compute thanks to a specific method (computeStat()).
<template>
<apexcharts width="500" type="bar" :options="chartOptions" :series="series"></apexcharts>
</template>
<script>
export default {
name: 'Results',
components: {
apexcharts: VueApexCharts
},
data() {
return {
results: '',
correctAns: 0,
uncorrectAns: 0,
chartOptions: {
chart: {
id: 'vuechart-example'
},
xaxis: {
categories: ['Correct Answers', 'Uncorrect Answers']
}
},
series: [
{
name: 'series-1',
data: [this.correctAns, this.uncorrectAns]
}
]
}
},
methods: {
computeStat() {
var i
for (i = 0; i < this.results.length; i = i + 1) {
if (this.results[i].answerCorrect == true) {
this.correctAns = this.correctAns + 1
} else {
this.uncorrectAns = this.uncorrectAns + 1
}
}
}
},
created() {
this.results = this.$route.params.output
this.computeStat()
var i
for (i = 0; i < this.results.length; i = i + 1) {
console.log('bestPractice ' + i + ':' + this.results[i].bestPract)
}
}
}
</script>
When I run the application, the chart isn't displayed and I get this error message on the browser console:
I would like to know the nature of this error and if there is a correct way to display "correctAns" and "uncorrectAns" values in the chart.
There's a couple of problems here around your series property...
When you define series, both this.correctAns and this.uncorrectAns are undefined (this is the source of your problem)
Because series is statically defined, it will never update as you make changes to this.correctAns and this.uncorrectAns
The solution is to convert series into a computed property. Remove it from data and add
computed: {
series () {
return [
{
name: 'series-1',
data: [this.correctAns, this.uncorrectAns]
}
]
}
}
Demo ~ https://jsfiddle.net/ynLfabdz/
Given you seem to be treating results as an array, you should initialise it as such instead of an empty string, ie
results: [], // not ''
I fixed the issue by simple check if the array is undefined then return empty if not return the chart with my values
const Amount = [
{
name: 'Salary Amount',
data: salary[0] === undefined ? [] : salary
},
{
name: 'Over Time Amount',
data: overTime[0] === undefined ? [] : overTime
},
true
]
I have a data set that contains many fields. I have no control over the creation of this JSON. Sample:
data = [
{
'maparea':'3704000063',
'relatedsource':null,
'empcount':'198390',
'response':'78',
'mean':'61663.00',
},
...
]
The chart code is:
Highcharts.mapChart('container', {
chart: {
map: geojson
},
title: {
text: 'GeoJSON in Highmaps'
},
mapNavigation: {
enabled: true,
buttonOptions: {
verticalAlign: 'bottom'
}
},
colorAxis: {
tickPixelInterval: 100
},
series: [{
data: data,
keys: ['maparea', 'relatedsource', 'empcount', 'response', 'mean'],
joinBy: ['fips', 'maparea'],
name: 'Random data',
states: {
hover: {
color: '#a4edba'
}
},
dataLabels: {
enabled: true,
format: '{point.properties.postal}'
}
}]
});
The geoJSON uses fips to label the areas (in this case counties in NC). The map shows the state and county elements. However, no data is used to plot. This is because the HighMaps code is expecting a value element to be present in the data I think.
Is there a way to tell HighMaps what element in the data set to use to shade the choropleth?
I don't see any option to map your unique data shape to the expected keys in the data according to the docs. Per your comment this is possible with an array, but it doesn't seem to be possible with an object.
However, it's pretty simple to just remap your object to the required shape. The code below gives a partial example.
let dataMapped = data.map(obj => {
var median = Number(obj.median);
return Object.assign(obj, { name: obj.maparea, value: median });
});
And then use dataMapped as the value for your data.
There might be a more elegant way to do this in ES6 with object spread and avoid the Object.assign I am using to merge the old object with new attributes, but I don't have time to research that at the moment.
I have a chart with 3 different series and I've included Range Selector from Highstock. I want to be able to select which one of the 3 series is the one set in the Range-Selector. Is there any way to dynamically assign the serie to the Range Selector?
I create the chart with 3 series like this:
//A,B,C data array
Highcharts.stockChart('container', {
series: [
{ data: A },
{ data: B },
{ data: C }
]
});
What I want to accomplish is to be able to select either A,B or C as the serie active to see in the Range-Selector preview.
Here's a jsfiddle: https://jsfiddle.net/usvonfjh/1/
You can show each series in navigator by setting series.line.showInNavigator = true. To set it dynamically use series.update() method where you can pass new options for series.
Code:
let dates = [1496268000000, 1504216800000, 1512082800000, 1519858800000, 1527804000000, 1535752800000, 1543618800000, 1551394800000, 1559340000000, 1567288800000];
let aSerie = dates.map((e, i) => [e, i < 5 ? null : i]);
let bSerie = dates.map((e, i) => [e, i + 1]);
let cSerie = dates.map((e, i) => [e, i * 2]);
Highcharts.stockChart('container', {
chart: {
events: {
load: function() {
const chart = this;
setTimeout(() => {
chart.series[1].update({
showInNavigator: false
});
}, 2000);
}
}
},
rangeSelector: {
verticalAlign: 'top'
},
series: [{
name: "aSerie",
showInNavigator: true,
data: aSerie
}, {
name: "bSerie",
showInNavigator: true,
data: bSerie
}, {
name: "cSerie",
showInNavigator: true,
data: cSerie
}]
});
Demo:
https://jsfiddle.net/BlackLabel/pxw09zrc/
API reference:
https://api.highcharts.com/highstock/series.line.showInNavigator
https://api.highcharts.com/class-reference/Highcharts.Series#update
i make jsonstring like this:
{ "dataTarget":["[Date.UTC(2016,3,01),10.00]",
"[Date.UTC(2016,1,01),5.00]"],
"dataRealisasi" :["[Date.UTC(2016,3,01),10.00]",
"[Date.UTC(2016,1,01),5.00]"]
}
i retrieve it thru jquery ajax and parse it
var dataChart = JSON.parse(msg.d);
var dataTarget = dataChart['dataTarget']
var dataRealisasi = dataChart['dataRealisasi']
i console log dataTarget , this is the result :
["[Date.UTC(2016,3,01),10.00]", "[Date.UTC(2016,1,01),5.00]"]
what i need is a variable that is like this
[
[Date.UTC(2016,3,01),10.00],
[Date.UTC(2016,1,01),5.00]
]
which i can pass it as a variable into this
$('#container3').highcharts({
chart: {
type: 'spline'
},
title: {
text: 'Monitoring Proyek'
},
subtitle: {
text: 'Proyek'
},
xAxis: {
type: 'datetime',
dateTimeLabelFormats: { // don't display the dummy year
month: '%e. %b',
year: '%b'
},
title: {
text: 'Date'
}
},
yAxis: {
title: {
text: 'Target (%)'
},
min: 0
},
tooltip: {
headerFormat: '<b>{series.name}</b><br>',
pointFormat: '{point.x:%e. %b}: {point.y:.2f} %'
},
plotOptions: {
spline: {
marker: {
enabled: true
}
}
},
series: [{
"name": "Proyeksi Target",
"data": dataTarget // this is the variable
}, {
name: 'Realisasi',
data:
dataRealisasi // this is the variable
}]
});
update:
the problem is when i create json string without the double quote then JSON.parse it returns error...
i already change the server side function and return object :
[["Date.UTC(2016,3,01)",10.00], ["Date.UTC(2016,1,01)",5.00]]
, now i need to remove the the double quotes and change it too :
[[Date.UTC(2016,3,01),10.00], [Date.UTC(2016,1,01),5.00]]
need help here...
You can transform json like this (do not use eval):
[
"[Date.UTC(2016,3,01),10.00]",
"[Date.UTC(2016,1,01),5.00]"
].map(function(v){
return new Function('return ' + v)();
});
but strongly recommend you just use the timestamp, because this transform is have a bit more cost then as usual
Don't know about the leading 0 so I would clean that off
// the data
var data = [
"[Date.UTC(2016,3,01),10.00]",
"[Date.UTC(2016,1,01),5.00]"
];
var clean = function(n){ // remove leadin zero as we want the numbers.
return Number(n.replace(/^0+?/, ""));
}
// removes unneeded characters "Date.UTC(", ")","[","]"
// split to an array of strings. Clean of leading zeros ? and convert to numbers
var convert = function(str){
var n = str.replace(/Date.UTC\(|\)|\[|\]/g, "").split(",").map(clean);
return [Date.UTC(n[0], n[1], n[2]), n[3]]; // get date and return the array item as an array
}
// Start the ball rolling.
try{
data = data.map(convert);
}catch(e){
console.log("You are having a bad day!");
}
// data === [[1459468800000, 10], [1454284800000, 5]];
On debug. when execution is leaving the controller I debug and the variable contains :
?sArray
{string[17, 2]}
[0, 0]: "Arecleoch"
[0, 1]: "21"
[1, 0]: "Barnesmore"
[1, 1]: "3"
etc etc....
then in the javascript its received as :
?sdata
{...}
[0]: "Arecleoch"
[1]: "21"
[2]: "Barnesmore"
[3]: "3"
[4]: "Beinn An Tuirc"
[5]: "1"
[6]: "Beinn An Tuirc Phase 2"
etc
so the pie is displayed as one solid circle of colour
puzzled, any ideas?
controller code below :
public JsonResult GetChartData_IncidentsBySite()
{
var allSites = _securityRepository.FindAllSites();
var qry = from s in _db.Sites
join i in _db.Incidents on s.SiteId equals i.SiteId
group s by s.SiteDescription
into grp
select new
{
Site = grp.Key,
Count = grp.Count()
};
string[,] sArray = new string[qry.Count(),2];
int y = 0;
foreach (var row in qry.OrderBy(x => x.Site))
{
if ((row.Count > 0) && (row.Site != null))
{
sArray[y, 0] = row.Site.ToString();
sArray[y, 1] = row.Count.ToString();
y++;
}
}
return Json(sArray , JsonRequestBehavior.AllowGet);
}
Here is the javascript code :
$.getJSON(url, null, function(sdata) {
debugger;
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
plotBackgroundColor: null,
plotBorderWidth: null,
plotShadow: false
},
title: {
text: 'Number of Environmental Incidents by Site'
},
tooltip: {
formatter: function() {
return '<b>' + this.point.name + '</b>: ' + this.y + ' %';
}
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: false
},
showInLegend: true
}
},
series: [{
type: 'pie',
name: 'Incidents by Site',
data: sdata
}]
});
});
});
In the version that works, data is an Array of Arrays of String ;
data: [["Arecleoch",21], ...
(Notice there is no oppening quotes before the first bracket).
In the version that does not work, it is a String representing the Array.
I suspect the charts API only expect an Array (in this case, an array of array, actually).
So it depends on what this does :
$.getJSON(url, null, function(data) {
// What is the type of data here ?
From your controller and the display of your debugger, I think data is itself an Array of Arrays. You should directly pass it to the charts API (without the sData = data.toString()) function wich actually transforms the Array ['a', 'b', 'c'] into a String representing the array, like "['a', 'b', 'c']");
// Callback parameter renamed to show it is an Array of Arrays
$.getJSON(url, null, function(aaData) {
// ... skipped ...
series: [{
type: 'pie',
name: 'Incidents by Site',
data: aaData /* Use the Array itself */
}]
Edit : my solution will only work if the controller output something like :
{
data : [[ "Arecleoch", 21], ["Whatever", 42]]
}
However it seems like your controller returns something like
{
data : "[['Arecleoch', 21],['Whatever', 42]]"
}
(Maybe without the { data : } part, I don't know if you need a top-level element or if you are derectly returning the Array in JSON)
Is that the case ? If so, then you'll have to either :
change the controller
parse the string on the client side, in javascript