I am using angularjs highchart by integrating the DI of highcharts-ng
I have created different type of charts by following options
var chart = {
options: {
chart: {
type: 'bar'
}
},
title: {
text: chartData.name
},
subtitle: {
text: chartData.subname
},
rangeSelector: {
enabled:true,
selected: 1
},
xAxis: {
title: {
text: chartData.x.title
}
},
yAxis: {
title: {
text: chartData.y.title
}
},
series: [{
name: chartData.data[0].name,
data: chartData.data[0].data,
dashStyle: 'longdash'
}, {
name: chartData.data[1].name,
data: chartData.data[1].data,
dashStyle: 'dot'
}, {
name: chartData.data[2].name,
data: chartData.data[2].data
}]
}
I have added rangeslider options but its not reflecting in chart.
How to integrate highchart range slider in angualrjs
Include a reference to highstock instead of highcharts. Both are compatible with highcharts-ng, but only highstock supports rangeSelector. Then, move rangeSelector into the options object. Note - "range slider" functionality is called navigator in the highstock docs, and must also be added to options.
var chart = {
options: {
chart: {
type: 'bar'
},
rangeSelector: {
enabled: true
},
navigator: {
enabled: true
}
}
...
};
Here is a demo, from highcharts-ng's GitHub page:
http://jsfiddle.net/pablojim/r88yszk0/
Related
I want to show the user about which nodes are some sort of type in network graph of Highchart JS.
For example, the red node would be about "car" and the black node would be about "person".
How can I implement such a legend in Highchart Js?
Here is my codepen.
Highcharts.seriesTypes.networkgraph.prototype.drawLegendSymbol = Highcharts.LegendSymbolMixin.drawRectangle;
Highcharts.chart('container', {
chart: {
type: 'networkgraph'
},
plotOptions: {
networkgraph: {
keys: ['from', 'to']
}
},
legend: {
enabled: true
},
series: [{
showInLegend: true,
data: [
['A', 'B'],
['C','D'],
['E','F']
],
nodes:[{
id:'A',
color:'#ff1000'
},{
id:'B',
color:'#222222'
},
{
id:'C',
color:'#ff1000'
},
{
id:'D',
color:'#222222'
},
{
id:'E',
color:'#ff1000'
},
{
id:'F',
color:'#222222'
},]
}]
});
Thank you in advance.
Have you tried adding the dataLabel to series property and add a name to your nodes.
{
id: "A",
color: "#ff1000",
name: "car" <--------- name property
},
Something like this:
series: {
dataLabels: {
linkFormat: '',
enabled: true,
format: "{point.name}",
crop: false,
defer: false,
useHtml: true,
},
}
Full example:
https://codepen.io/tiagotedsky/pen/zYZYOLR
I want to have multiple highcharts with different data in my page , without having to repeat the highchart code.
here is how i define my highchart
chartOptions: {
chart: {
type: "pie"
},
title: {
text: ""
},
credits: {
enabled: false
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: "pointer",
dataLabels: {
enabled: true,
format: '<b>{point.name}</b>: {point.percentage:.1f} %'
}
}
},
series: [
{
name: 'Comparison',
data: [],
},
]
},
I call it to the html like this-
<highcharts :options="chartOptions" id="chart1"></highcharts>
I use the event bus listener to send the data to the highchart series
EventBus.$on("btn-clicked", data => {
this.chartOptions.series[0].data = data.newData;
});
Since i am using the highchart-vuejs wrapper i am able to repeat the highcharts, but all the charts will get the same data.Is there a way that i could send the data to a particular chart so it is different from the others?
You're passing down chartOptions into the highcharts component. If you've defined this data on the parent component, Vue will have made it reactive, so when you change the data the chart will update automatically.
Below is a basic example of how this would work:
<template>
<div>
<highcharts :options="chartOptions[0]"></highcharts>
<highcharts :options="chartOptions[1]"></highcharts>
<button #click="changeData">Change data for first chart</button>
</div>
</template>
<script>
import { Chart } from "highcharts-vue";
export default {
components: {
highcharts: Chart
},
data() {
return {
chartOptions: [
{
series: [
{
data: [1, 2, 3]
}
]
},
{
series: [
{
data: [4, 5, 6]
}
]
},
]
}
},
methods: {
changeData() {
this.chartOptions[0].series[0].data = [4, 8, 1];
}
}
};
</script>
EDIT:
To create multiple charts with the same options, you could create a custom chart component, and pass in just the data series as a prop:
<template>
<highcharts :options="chartOptions"></highcharts>
</template>
<script>
import { Chart } from "highcharts-vue";
export default {
name: 'CustomPie',
components: {
highcharts: Chart
},
props: ['data'],
data() {
return {
chartOptions: {
chart: {
type: "pie"
},
title: {
text: ""
},
credits: {
enabled: false
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: "pointer",
dataLabels: {
enabled: true,
format: '<b>{point.name}</b>: {point.percentage:.1f} %'
}
}
},
series: [
{
name: 'Comparison',
data: this.data,
},
]
},
}
},
watch: {
data(newVal) {
this.chartOptions.series[0].data = newVal;
}
}
};
</script>
Note that you have to set up a watcher on the data prop, in order to update the components chartOptions when the data changes.
And your parent component (where you're displaying the charts) would look something like this:
<template>
<div>
<CustomPie :data="chartData1" />
<CustomPie :data="chartData2" />
<button #click="changeData">Change data for first chart</button>
</div>
</template>
<script>
import CustomPie from "./CustomPie";
export default {
components: {
CustomPie
},
data() {
return {
chartData1: [1,2,3],
chartData2: [4,5,6]
}
},
methods: {
changeData() {
this.chartData1 = [4, 8, 1];
}
}
};
</script>
I need some help with the following issue: it looks like since the latests Highcharts update (v7.0.2 2019-01-17), my pages are not working only when refreshing in background. If the webpage is always visible on my screen, everything will go smoothly, but if I have another chrome tab displayed on my screen, the update will not work and I will have this error:
highcharts.src.js:39446 Uncaught TypeError: Cannot read property 'pos' of undefined
at a.SVGElement.step (highcharts.src.js:39446)
at a.SVGElement.animate (highcharts.src.js:3654)
at r.animate (highcharts.src.js:39437)
at r.x (highcharts-more.src.js:7599)
at r.a.(anonymous function) [as animate] (https://code.highcharts.com/highcharts.js:20:270)
at render (highcharts.src.js:35110)
at highcharts.src.js:28431
at Array.forEach (<anonymous>)
at a.Chart.renderSeries (highcharts.src.js:28429)
at a.Chart.render (highcharts.src.js:28570)
The Javascript code for this chart is as follows:
Highcharts.chart('MychartID', {
chart: {
zoomType:'x',
alignTicks: false
},
tooltip: {
shared:false,
},
title: {
text: 'Title'
},
xAxis: {
type: 'category',
title: {
enabled: false,
text: 'PTU',
},
},
yAxis: [{
lineWidth: 1,
title: {
text: 'y1'
}
},
{
lineWidth: 1,
title: {
text: 'y2'
}
},
],
plotOptions: {
line: {
dataLabels: {
enabled: false,
},
},
column: {
dataLabels: {
enabled: true,
},
}
},
series: [
{
yAxis: 1,
type: 'column',
name: 'serie1',
data: serie1
},
{
name: 'serie2',
data: serie2
},
]
});
Do you have any idea of what is going wrong?
Thank you for your help!
This issue was a bug and it is fixed. It will be available in the next release of Highcharts.
The solution before release is to use code from Highcharts GitHub master branch where this bug is solved. You can download it here: https://github.highcharts.com/master/highcharts.src.js
I would like to make the transition from pre-version 5.0.0 Highcharts and highcharts-ng version 0.0.12 to the latest versions.
I know there are some critical changes in the chart object, as well as with how highcharts-ng works in the latest versions. I have been searching for an example on how to set my Angular environment up using these latest versions, but it seems there is a great shortage on resources using these versions.
I was hoping you could help me with setting this up.
I have tried numerous changes myself, but I keep getting errors I did not get with the older versions of the scripts. Errors such as:
"Unable to get property of 'series' of undefined or null reference
(at $doCheck
(http://localhost:50262/app/vendorScripts/highcharts-ng.js:51:16))",
"Cannot set property 'getChartObj' of undefined" (at HighChartNGController.$onInit (highcharts-ng.js:36)),
"Multiple definitions of a property not allowed in strict mode (ChartFactory)"
This is my working solution pre-latest versions:
Here is my ChartFactory:
'use strict';
angular.module('portalDashboardApp')
.factory('ChartFactory', function () {
return {
getChartConfig: function () {
return {
options: {
chart: {
type: 'bar',
height: 400,
spacingTop: 30,
spacingBottom: 10,
spacingLeft: 10,
spacingRight: 50,
zoomType: 'x',
backgroundColor: false,
resetZoomButton: {
position: {
x: 0,
y: 40
}
}
},
credits: {
enabled: false
},
navigation: {
buttonOptions: {
y: -30
}
},
tooltip: {
formatter: function () {
return '<b>' + this.y + ' ' + this.series.name + '</b>';
}
},
plotOptions: {
column: {
stacking: ''
},
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: true,
},
showInLegend: true
},
series: {
animation: true,
point: {
events: {
click: function () {
}
}
},
dataLabels: {
enabled: true,
format: ''
}
}
},
exporting: {
sourceWidth: 1600,
sourceHeight: 800,
// scale: 2 (default)
chartOptions: {
subtitle: null
},
buttons: {
contextButton: {
text: 'Export Chart'
}
}
}
},
title: {
text: false
},
xAxis: {
type: 'category'
},
yAxis: {
gridLineWidth: 1,
title: {
text: 'Count'
},
labels:
{
enabled: true,
format: '{value}'
}
},
legend: {
layout: 'vertical',
floating: true,
backgroundColor: '#FFFFFF',
align: 'right',
verticalAlign: 'top',
y: 60,
x: -60
},
series: [{}],
loading: false
};
}
};
});
This is how I would create a chart in my Angular controller:
I would inject my ChartFactory
Get my data from mt API call
And then set up, customize and apply my data for my chart using these methods:
function volumeGraphConfig(timeline_data, time_trend) {
$scope.VolumeGraphChartConfig = ChartFactory.getChartConfig();
$scope.VolumeGraphChartConfig.chart.type = 'column';
}
function populateVolumeData(timeline_data, time_trend) {
$scope.VolumeGraphChartConfig.xAxis.categories = timeline_data;
$scope.VolumeGraphChartConfig.series = [{
name: 'Twitter',
data: time_trend.Twitter,
color: twitterColor
}, {
name: 'Instagram',
data: time_trend.Instagram,
color: instagramColor
}, {
name: 'Youtube',
data: time_trend.Youtube,
color: youtubeColor
}];
$scope.VolumeGraphChartConfig.tooltip = {
pointFormat: '<span style="color:{series.color}">{series.name}</span>: <strong>{point.y}</strong> mentions<br/>',
shared: false
};
}
I would then display my chart using this HTML div:
<highchart id="FacebookVolume" config="volumeGraphChartConfig"></highchart>
How can I change this to work with the latest versions? Thank you!
The first two errors:
Cannot set property 'getChartObj' of undefined
Unable to get property of 'series' of undefined or null reference
happen when your config object is undefined.
For your case, you need to use the same variable you declared on your $scope
<highchart id="FacebookVolume" config="VolumeGraphChartConfig"></highchart>
(capital V)
I am using HighCharts to make a graph with columns, drilldown series and scatter. The problem which I am having, is that the HighChart is created before the $.getJSON function is succesfully exicited. I have found several other articles, but non yet where two $.getJSON functions are called. The code which I am using:
$(function () {
// Create the chart
var options = {
chart: {
renderTo: 'container_genomefraction',
type: 'column',
events: {
// Declare the events changing when the drilldown is activated
drilldown: function(options) {
this.yAxis[0].update({
labels: {
format: '{value}'
},
title: {text : "Gbp"}
}, false, false);
options.seriesOptions.dataLabels = {
format: '{point.y:.1f}'
};
options.seriesOptions.tooltip = {
pointFormat: '<span style="color:{point.color}">{point.name}</span>: <b>{point.y:.2f}</b> of total<br/>'
};
},
// Declare the events changing when the drillup is activated
drillup: function () {
this.yAxis[0].update({
labels: {
format: '{value}%'
},
title: {text : "Percentages"}
}, false, false);
}
}
},
title: {
text: 'Comparison'
},
xAxis: {
type: 'category'
},
yAxis: [{
title: {
enabled: true,
text: 'Percentages',
style: {
fontWeight: 'normal'
}
},
labels: {
format: '{value}%'
}
},{
min: 0,
title :{
text : 'input'
},
labels: {
format : '{value}'
},
opposite: true
}],
legend: {
enabled: false
},
plotOptions: {
series: {
marker: {
fillColor: '#FFFFFF',
lineWidth: 2,
lineColor: null, // inherit from series
size : 50
},
borderWidth: 0,
dataLabels: {
enabled: true,
format: '{point.y:.1f}%'
}
}
},
tooltip: {
headerFormat: '<span style="font-size:11px">{series.name}</span><br>',
pointFormat: '<span style="color:{point.color}">{point.name}</span>: <b>{point.y:.2f}%</b> of total<br/>'
},
// Declare an empty series
series: [{
name: '',
colorByPoint: true,
data: []
}],
credits: {
enabled: false
},
// Declare an empty drilldown series
drilldown: {
series: [{
name : '',
id: '',
data: []
}]
}
};
// Your $.getJSON() request is now synchronous...
$.ajaxSetup({
async: false
});
// Get the input into one series
$.getJSON('/uploads/fraction.json', function (list) {
options.series = list;
});
// Get the drilldown estimated and total size into one series
$.getJSON('/uploads/drilldown.json', function (list2) {
options.drilldown.series = list2;
var chart = new Highcharts.Chart(options);
});
$.ajaxSetup({
async: true
});
});
My JSONs are formatted:
fraction.json
[{"name":"1","colorByPoint":true,"data":[{"name":1,"y":80,"drilldown":1},{"name":2,"y":87,"drilldown":2},{"name":3,"y":105.71428571429,"drilldown":3}]},{"name":"input","dataLabels":"{enabled,false}","yAxis":1,"type":"scatter","data":[{"y":38,"name":1,"drilldown":1},{"y":"","name":2,"drilldown":2},{"y":27,"name":3,"drilldown":3}],"tooltip":{"headerFormat":"<span style='font-size:11px'>{series.name}<\/span><br>","pointFormat":"<span style='color:{point.color}'>{point.name}<\/span>: <b>{point.y}<\/b><br\/>"}}]
drilldown.json
[{"name":1,"id":1,"data":[["Total",2],["Estimated",2.5]]},{"name":2,"id":2,"data":[["Total",3.9],["Estimated",4.5]]},{"name":3,"id":3,"data":[["Total",3.7],["Estimated",3.5]]}]
When the page is loaded, the graph displays the values of the previous search done and when I reload the page, the correct data is shown. Could someone please help me out?
Add the second getJSON method in the first getJSON success callback like this:
//Get the genome fraction into one series
$.getJSON('/uploads/fraction.json', function (list) {
options.series = list;
//Get the drilldown estimated and total genome size into one series
$.getJSON('/uploads/drilldown.json', function (list2) {
options.drilldown.series = list2;
var chart = new Highcharts.Chart(options);
});
});