I've an AngularJS app rendered by ASP.net MVC. AngularJS is using HighCharts (not highcharts-ng though). I've below script references:
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<script src="https://code.highcharts.com/modules/offline-exporting.js"></script>
And, I've below in chart options:
exporting: {
enabled: true,
chartOptions: { // specific options for the exported image
plotOptions: {
series: {
dataLabels: {
enabled: false
}
}
}
},
scale: 1,
fallbackToExportServer: true
}
Yet, the export burger menu is not showing. What am I doing wrong?
JSFiddle for the Angular version that works, and nothing in fact needs to be done except adding the two exporting*.js.
I have added exporting fragment of the JSON though. But omitting that part also brings up the burger. You may want to check with this. No jQuery is required, I take that statement back. Direct use of the API inside the controller, that's all.
in the controller:
angular.module('myModule', [])
.controller('myController', function($scope) {
Highcharts.chart('container', {
title: {
text: 'Temperature Data'
},
xAxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
]
},
series: [{
data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
}],
exporting: {
enabled: true,
chartOptions: { // specific options for the exported image
plotOptions: {
series: {
dataLabels: {
enabled: false
}
}
}
},
scale: 1,
fallbackToExportServer: true
}
});
});
Also check if the exporting.js loads over https.
Related
I have two stacked column charts next to each other, sharing the same categories, and I would like them to both be controlled by the same legend. So that there is only one visible legend, but clicking the items affects both charts.
I found this jsfiddle that accomplishes this using JQuery, and this StackOverflow post that accomplishes it in React using class components.
$(function () {
$('#container1').highcharts({
xAxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
},
legend: {
enabled: false
},
series: [{
id: 'someId',
name: 'Apples',
data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
}, {
id: 'someId',
name: 'Bananas',
data: [71,74,76,77,63,74,72,46,23.8,62,59.6,40.5]
}]
});
$('#container2').highcharts({
xAxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
},
plotOptions: {
series: {
events: {
legendItemClick: function (event) {
var XYZ = $('#container1').highcharts(),
series = XYZ.get(this.options.id); //get corresponding series
if (series) {
if (this.visible) {
series.hide();
} else {
series.show();
}
}
}
}
}
},
series: [{
id: 'someId',
name: 'Apples',
data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
}, {
id: 'someId',
name: 'Bananas',
data: [71,74,76,77,63,74,72,46,23.8,62,59.6,40.5]
}]
});
});
However I am having trouble figuring out how to accomplish this using functional components in React, since you can't use the "this" keyword to access the chart options, but putting the click event function outside of the functional component makes it impossible to use a DOM ref to the other chart.
I am using Angular Directives to render Highcharts visuals and am trying to change the directive used based on User input. For testing, attempting to switch between line and column charts.
The directives are:
myApp.directive('columnChart', function () {
return function (scope, element, attrs) {
initChart();
function initChart() {
var chartConfig = {
chart: {
type: 'column',
zoomType: 'xy'
},
title: {
text: ''
},
xAxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
},
yAxis: [{
min: 0,
title: {
text: 'Y Axis Label'
},
}],
series: [{
data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
}]
};
var chart = $(element).highcharts(chartConfig);
}
};
});
and
myApp.directive('lineChart', function () {
return function (scope, element, attrs) {
initChart();
function initChart() {
var chartConfig = {
chart: {
type: 'line',
zoomType: 'xy'
},
title: {
text: ''
},
xAxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
},
yAxis: [{
min: 0,
//max:200,
title: {
text: 'Y Axis Label'
},
}],
series: [{
data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
}]
};
var chart = $(element).highcharts(chartConfig);
}
};
});
I have a simple test page with buttons that change the directive:
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<div ng-controller="MyCtrl">
<button ng-click="setLineChart()">Set Line Chart</button>
<button ng-click="setColumnChart()">Set Column Chart</button>
<div id="container" column-Chart style="min-width: 400px; height: 400px; margin: 0 auto"></div>
</div>
and the code to set the Directive:
$scope.setLineChart = function() {
var docElement = document.getElementById("container");
var scope = angular.element(docElement).scope();
var element = angular.element(docElement);
element.html('<div id="chartContainer" line-Chart style="min-width: 400px; height: 400px; margin: 0 auto"></div>');
console.log("element: " , element);
$compile(element)(scope);
};
Clicking on the Set Line Chart button causes the Directive for the line chart to get called, but the chart still resolved as a column chart.
Here is the jsfiddle: https://jsfiddle.net/MFRTest/xsadzv4f/12/
I appreciate any insight into what I am missing
With the AngularJS framework, avoid manipulating DOM in controllers. The framework separates concerns to make the app more easily understood, debugged, tested, and maintained.
Instead have a directive that create highcharts based on the Model furnished by the Controller:
app.directive("highchart", function() {
return {
link: postLink
}
function postLink(scope, elem, attrs) {
scope.$watch(attrs.highchart, function (chartConfig) {
elem.highcharts(chartConfig);
}, true)
}
})
Usage:
<button ng-click="$ctrl.chart = $ctrl.lineChart">Set Line Chart</button>
<button ng-click="$ctrl.chart = $ctrl.colChart">Set Column Chart</button>
<div highchart="$ctrl.chart"
style="min-width: 300px; height: 300px; margin: 0 auto">
</div>
The DEMO
angular.module("app",[])
.directive("highchart", function() {
return {
link: postLink
}
function postLink(scope, elem, attrs) {
scope.$watch(attrs.highchart, function (chartConfig) {
elem.highcharts(chartConfig);
})
}
})
.controller("ctrl", function() {
this.colChart = {
chart: {
type: 'column',
zoomType: 'xy'
},
title: {
text: ''
},
xAxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
]
},
yAxis: [{
min: 0,
//max:200,
title: {
text: 'Y Axis Label'
},
}],
series: [{
data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
}]
};
this.lineChart = {
chart: {
type: 'line',
zoomType: 'xy'
},
title: {
text: ''
},
xAxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
},
yAxis: [{
min: 0,
//max:200,
title: {
text: 'Y Axis Label'
},
}],
series: [{
data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
}]
};
})
<script src="//unpkg.com/jquery"></script>
<script src="//unpkg.com/highcharts"></script>
<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="app" ng-controller="ctrl as $ctrl">
<h3>Highchart Directive DEMO</h3>
<button ng-click="$ctrl.chart = $ctrl.lineChart">
Set Line Chart
</button>
<button ng-click="$ctrl.chart = $ctrl.colChart">
Set Column Chart
</button>
<div highchart="$ctrl.chart"
style="min-width: 300px; height: 180px; margin: 0 auto">
</div>
</body>
I am trying to use Highcharts for plotting charts and also wants them to be zoomable.
Below is chart I am plotting
var mychart = new Highcharts.Chart({
chart: {
type: 'line',
zoomType: 'x'
},
xAxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
},
series: [{
data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
}]
});
I am able to see chart and its zoomable.
but what I want to do is listen for afterSetExtremes event from my backbone view.
Below is what I tried to do for listening event.
this.listenTo(mychart.chartOptions.xAxis, 'afterSetExtremes', function() {
console.log("listening to ");
});
But I am getting error Uncaught TypeError: undefined is not a function
Am I missing something or doing it wrong?
How can I listen for afterSetExtremes event without mentioning it inside xAxis.events option from my backbone view ?
Thanks
Try to replace
mychart.chartOptions.xAxis
with
mychart.chartOptions.xAxis.events
Using an AngularJS directive, I am able to load a Highcharts graph. However, my event handler for clicking on a point is not being executed.
http://plnkr.co/edit/pxU0IsBTrvcEwr2Znf5d?p=preview
JS
var app = angular.module('charts', []);
app.directive('highchart', function () {
return {
restrict: 'E',
template: '<div></div>',
replace: true,
link: function (scope, element, attrs) {
scope.$watch(function() { return attrs.chart; }, function() {
if(!attrs.chart) return;
var chart = JSON.parse(attrs.chart);
$(element[0]).highcharts(chart);
});
}
}
});
function Ctrl($scope) {
$scope.example_chart = {
xAxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
},
plotOptions: {
series: {
cursor: 'pointer',
point: {
events: {
click: function() {
alert ('Category: '+ this.category +', value: '+ this.y);
}
}
}
}
},
series: [{
data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
}]
};
}
HTML
<section ng-app='charts'>
<div ng-controller="Ctrl">
<highchart chart='{{example_chart}}'></highchart>
</div>
</section>
It seems to be working if you use the data from the scope directly so it's something with JSON parsing from within the attribute. Perhaps the function tries to somehow get evaluated? After examining the attribute string with the chart data, you can see the event: function contains blank objects.
plunker: http://plnkr.co/edit/QyccE0NDRfUCTuxTftUV?p=preview
I am new to Angular JS and trying to render my highcharts (Basic Line) by creating a directive. Please tell me the approach I should follow here. Any help would be appreciated.
Here is my script for the highcharts:
<script type="text/javascript">
$(function () {
$('#container').highcharts({
chart: {
type: 'line',
marginRight: 130,
marginBottom: 25
},
title: {
text: 'Monthly Average Temperature',
x: -20 //center
},
subtitle: {
text: 'Source: WorldClimate.com',
x: -20
},
xAxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
},
yAxis: {
title: {
text: 'Temperature (°C)'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
tooltip: {
valueSuffix: '°C'
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'top',
x: -10,
y: 100,
borderWidth: 0
},
series: [{
name: 'Tokyo',
data: [7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6]
}, {
name: 'New York',
data: [-0.2, 0.8, 5.7, 11.3, 17.0, 22.0, 24.8, 24.1, 20.1, 14.1, 8.6, 2.5]
}, {
name: 'Berlin',
data: [-0.9, 0.6, 3.5, 8.4, 13.5, 17.0, 18.6, 17.9, 14.3, 9.0, 3.9, 1.0]
}, {
name: 'London',
data: [3.9, 4.2, 5.7, 8.5, 11.9, 15.2, 17.0, 16.6, 14.2, 10.3, 6.6, 4.8]
}]
});
});
</script>
Example of pie chart:
http://jsfiddle.net/csTzc/
function MyCtrl($scope, limitToFilter) {
$scope.ideas = [
['ideas1', 1],
['ideas2', 8],
['ideas3', 5]
];
$scope.limitedIdeas = limitToFilter($scope.ideas, 2);
}
angular.module('myApp', [])
.directive('hcPie', function () {
return {
restrict: 'C',
replace: true,
scope: {
items: '='
},
controller: function ($scope, $element, $attrs) {
console.log(2);
},
template: '<div id="container" style="margin: 0 auto">not working</div>',
link: function (scope, element, attrs) {
console.log(3);
var chart = new Highcharts.Chart(options);
scope.$watch("items", function (newValue) {
chart.series[0].setData(newValue, true);
}, true);
}
}
});
Alternative implementation here: http://jsfiddle.net/pablojim/Cp73s/
This uses https://github.com/pablojim/highcharts-ng
This allows you to create a highchart with the below html:
<highchart id="chart1" series="chart.series" title="chart.title" options="chart.options"></highchart>
In the above case chart.series is an array of javascript objects representing the series on the chart - these take standard Highcharts options. These are then watched by angularjs for any changes.
chart.options is the highcharts initalisation options - also watched for changes. Although changes to this recreate the entire chart.
chart.title is the highcharts title object - also watched for changes.
app.directive('hcChart', function () {
return {
restrict: 'A',
template: '<div></div>',
scope: {
options: '='
},
link: function (scope , element, attribute) {
Highcharts.chart('chart', {
chartOptions: {
type: 'line'
},
title: {
text: 'Temperature data'
},
series: [{
data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
}]
});
}
}
});
<div id="chart" hc-chart>Placeholder for generic chart</div>
Make sure highchart lib is added in your index.html