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
Related
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 want to update high chart on real time in angular js after a particular time span and it should get reflects on html without user interaction in angular JS.
Below are code for Controller,Directive and HTML. I am using rest web service to fetch the data from back end.
Controller :
function dashboardController($scope, $http) {
this.$scope = $scope;
$scope.init=function(){
_refreshPageData();
function _refreshPageData() {
$http({
method : 'GET',
url : 'http://localhost:8080/SpringWebApp/rest/employee/monthlydata'
}).then(function successCallback(response) {
$scope.data = response.data;
var data = $scope.data;
var a = [];
parseInt($scope.data[0].data);
angular.forEach(data, function(data, key) {
a.push(parseInt(data.data));
});
console.log($scope.data);
$scope.chartConfig = {
xAxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
},
title: {
text: 'USD to EUR exchange rate from 2006 through 2008'
}, subtitle: {
text: document.ontouchstart === undefined ?
'Click and drag in the plot area to zoom in' :
'Pinch the chart to zoom in'
},
yAxis: { title: { text: 'Temperature (Celsius)' } },
tooltip: { valueSuffix: ' celsius' },
legend: { align: 'center', verticalAlign: 'bottom', borderWidth: 0 },
plotOptions: {
area: {
fillColor: {
linearGradient: { x1: 200, y1: 220, x2: 220, y2: 2221},
stops: [
[0, Highcharts.getOptions().colors[0]],
[1, Highcharts.Color(Highcharts.getOptions().colors[0]).setOpacity(0).get('rgba')]
]
},
marker: {
radius: 2
},
lineWidth: 1,
states: {
hover: {
lineWidth: 1
}
},
threshold: null
}
},
series: [{
type:'area',
data :a
}]
};
}, function errorCallback(response) {
console.log(response.statusText);
});
}
}
}
Directive :
var chartDirective = function () {
return {
restrict: 'E',
replace: true,
template: '<div></div>',
scope: {
config: '='
},
link: function (scope, element, attrs) {
var chart;
var process = function () {
var defaultOptions = {
chart: { renderTo: element[0] },
};
var config = angular.extend(defaultOptions, scope.config);
chart = new Highcharts.Chart(config);
};
process();
scope.$watch("config.series", function (loading) {
process();
});
scope.$watch("config.loading", function (loading) {
if (!chart) {
return;
}
if (loading) {
chart.showLoading();
} else {
chart.hideLoading();
}
});
}
};
};
Html :
<!DOCTYPE html>
<html lang="en">
<head>
<script data-require="angular.js#*" data-semver="1.2.5" src="http://code.angularjs.org/1.2.5/angular.js"></script>
<script data-require="jquery#*" data-semver="2.0.3" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script data-require="highcharts#*" data-semver="2.3.5" src="//cdnjs.cloudflare.com/ajax/libs/highcharts/2.3.5/highcharts.js"></script>
<script src="chartDirective.js"></script>
<script src="dashboardController.js"></script>
<script src="app.js"></script>
<meta charset="utf-8">
</head>
<body ng-app="app">
<div ng-controller="dashboardController">
<div ng-init="init()"></div>
<chart config="chartConfig"></chart>
</div>
</body>
</html>
You can make a request based on the interval using $interval
$interval(function() {
YourApi.response.then,
series.addPoint([whatever);
}, 1000);
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.
I am trying to display highcharts in my angular application
Below is my get_chart function which takes data from another function
function get_chart(data) {
alert('hello..' + data);
return {
xAxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
},
chart: {
height: 300,
width: 500,
type: 'column'
},
credits: {
enabled: false
},
plotOptions: {
series: {
cursor: 'pointer',
point: {
events: {
click: function() {
console.log ('Category: '+ this.category +', value: '+ this.y);
}
}
}
}
},
series: [{
data: [ data ]
}]
};
}
Then I am trying to send data from
$scope.renderChart = function(measurement){
$scope.showChart = false;
restApp.getMeasurementForCompID(comp.id, measurement.id).then(function(data){
console.log('getMeasurementForCompID data ');
console.log(data);
data = [10, 20];
$scope.example_chart = get_chart(data);
console.log($scope.example_chart);
$scope.showChart = true;
});
}
HTML
<div>
<highchart id="dash-chart" chart='example_chart'></highchart>
</div>
Highcharts directive
myapp.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 = scope.example_chart;
console.log('loading chart');
console.log(chart);
element.highcharts(chart);
});
}
}
});
console
But I am unable to display the charts with values 10,20.
What might be the problem here?
Thanks
I have solved my problem by doing following
<div>
<highchart ng-if="showChart" id="dash-chart" chart='example_chart'></highchart>
</div>
Thank you
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