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
Related
I'm trying to write a directive for HighCharts in AngularJS which supports two way data binding. On click of a function in the HTML, am trying to load the graph with new data.
Please check the below snipet.
HTML:
<hc-area-chart data="areaData"></hc-area-chart>
<button ng-click="updateGraph()">Update function</button>
Controller:
angular.module('myModule', [])
.directive('hcAreaChart', function () {
return {
restrict: 'E',
template: '<div></div>',
scope: {
title: '#',
data: '='
},
link: function (scope, element) {
Highcharts.chart(element[0], {
chart: {
type: 'area'
},
title: {
text: null
},
xAxis: {
categories: ['Mon', 'Tue', 'Wed', 'Thur', 'Fri', 'Sat', 'Sun']
},
plotOptions: {
pointStart: 4,
},
series: [{
showInLegend: false,
data: scope.data
}]
});
}
};
})
.controller('myController', function ($scope) {
$scope.areaData = [0,6,5,7,5,4.5,10];
$scope.updateGraphData = function () {
console.log("inside update function");
$scope.areaData = [10,20,30,40,50,60,70];
}
});
I think you should try something like this
link: function (scope, element) {
scope.$watch('data', function(){
Highcharts.chart(element[0], {
chart: {
type: 'area'
},
title: {
text: null
},
xAxis: {
categories: ['Mon', 'Tue', 'Wed', 'Thur', 'Fri', 'Sat', 'Sun']
},
plotOptions: {
pointStart: 4,
},
series: [{
showInLegend: false,
data: scope.data
}]
});
})
}
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 have a scenario where I need to show a pie-chart in a popup modal (used ui-bootstrap modal). I used c3.js for my pie-chart requirement (inside a directive).
The pie-chart is not loading inside the pop up. But to my surprise when I tried to debug the issue when I opened the console it is loading. When I re-size the window it is loading.
How can i fix this issue?
'use strict';
angular.module('App')
.directive('pieChartDirective', function() {
return {
restrict: 'A',
scope: {
chartdata: '=',
},
link: function(scope, elem, attrs) {
var chart = c3.generate({
bindto: '#chart',
data: {
columns: [
['Javascript', scope.chartdata.Javascript],
['HTML', scope.chartdata.HTML],
['Css', scope.chartdata.Css],
['Angular', scope.chartdata.Angular],
['Bootstrap', scope.chartdata.Bootstrap],
['Jquery', scope.chartdata.Jquery],
['Communication', scope.chartdata.Communication]
],
type: 'pie',
},
legend: {
show: false
},
tooltip: {
format: {
value: function(value, ratio, id, index) {
return value;
}
}
}
});
}
};
});
Html:
<div pie-chart-directive chartdata="oChartData">
<div id="chart"></div>
</div>
Are you shure, that you include your directive properly in your html code as
<div pie-chart-directive></div>
Maybe you have to change your restriction to 'E' to use your directive as a tag elment
<pie-chart-directive chartdata="myData"></pie-chart-directive>
The reason could be, that at the moment you try to generate the chart, your '#chart' div isn't yet present in the dom tree. Therefore you have to resize to trigger a new draw. Try to wait until the dom is loaded
$('#chart').ready(function() {
var chart = c3.generate({
bindto: '#chart',
data: {
columns: [
['Javascript', scope.chartdata.Javascript],
['HTML', scope.chartdata.HTML],
['Css', scope.chartdata.Css],
['Angular', scope.chartdata.Angular],
['Bootstrap', scope.chartdata.Bootstrap],
['Jquery', scope.chartdata.Jquery],
['Communication', scope.chartdata.Communication]
],
type: 'pie',
},
legend: {
show: false
},
tooltip: {
format: {
value: function(value, ratio, id, index) {
return value;
}
}
}
});
});
I got it by giving size property:
link: function(scope, elem, attrs) {
var chart = c3.generate({
bindto: '#chart',
size: {
width:400,
height:350
},
data: {
columns: [
['Javascript', scope.chartdata.Javascript],
['HTML', scope.chartdata.HTML],
['Css', scope.chartdata.Css],
['Angular', scope.chartdata.Angular],
['Bootstrap', scope.chartdata.Bootstrap],
['Jquery', scope.chartdata.Jquery],
['Communication', scope.chartdata.Communication]
],
type: 'pie',
},
legend: {
show: false
},
tooltip: {
format: {
value: function(value, ratio, id, index) {
return value;
}
}
}
});
}
So I'm using Highcharts-ng with Angular to create a combination chart of a spline chart and a column chart formatted as a histogram to show trends.
The way it works is that the on the load of the page, I only see the histogram, and not the spline. Changing the order does nothing.
It looks as though if I have the spline chart data hard-coded it shows, but using the program to add in the data after a service is called in does not work.
(function() {
'use strict';
angular
.module('app.widgets')
.directive('trends', trends);
trends.$inject = ['ResultsService'];
/* #ngInject */
function trends() {
var ddo = {
restrict: 'EA',
templateUrl: 'app/widgets/trends/trends.directive.html',
link: link,
scope: {
data: '=',
config: '='
},
controller: controller,
controllerAs: 'vm',
bindToController: true
};
return ddo;
function link(scope, element, attrs) {
}
function controller($scope, ResultsService) {
var vm = this;
var parent = $scope.widgetController;
var size = {
height: angular.element('li.widget-border.ng-scope.gridster-item')[1].style.height - 20 ,
width: angular.element('li.widget-border.ng-scope.gridster-item')[1].style.width - 20
};
vm.histogram = {
chart: {
zoomType: 'xy'
},
title: {
text: 'Average Monthly Weather Data for Tokyo'
},
subtitle: {
text: 'Source: WorldClimate.com'
},
xAxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
crosshair: true
},
yAxis: { // Primary yAxis
labels: {
style: {
color: Highcharts.getOptions().colors[2]
}
},
title: {
text: 'Events',
style: {
color: Highcharts.getOptions().colors[2]
}
}
},
tooltip: {
shared: true
},
legend: {
layout: 'vertical',
align: 'left',
x: 80,
verticalAlign: 'top',
y: 55,
floating: true,
backgroundColor: (Highcharts.theme && Highcharts.theme.legendBackgroundColor) || '#FFFFFF'
},
series: [{
name: 'Average',
type: 'spline',
data: [],
marker: {
enabled: true
}
}],
loading: false,
useHighStocks: false,
size: {
height: size.height,
width: size.width
}
};
vm.processChartData = processChartData;
vm.data = {
charts: {
}
};
ResultsService.getData().then(function(res) {
vm.data = {
charts: {}
};
vm.data.charts = processChartData(res);
vm.histogram.xAxis.categories = [];
vm.histogram.series.push ({
name: 'Events per month',
type: 'column',
data: [],
marker: {
enabled: true
}
});
console.log(vm.histogram.series);
angular.forEach(vm.data.charts.months, function(v,k){
vm.histogram.xAxis.categories.push(k);
vm.histogram.series[1].data.push(v);
});
vm.histogram.options = {
plotOptions: {
}
};
vm.histogram.options.plotOptions = {
column: {
borderWidth: 0.5,
groupPadding: 0,
shadow: true
},
};
console.log(vm.data.charts.months);
vm.histogram.xAxis.categories.sort();
var average = calculateAverage();
vm.histogram.series[0].data=average;
console.log(vm.histogram.series);
});
function swap(pos1, pos2){
var temp = vm.histogram.series[pos1];
vm.histogram.series[pos1] = vm.histogram.series[pos2];
vm.histogram.series[pos2] = temp;
}
function calculateAverage() {
var averageArray = [];
var total = 0;
angular.forEach(vm.data.charts.months, function(v,k){
console.log(v);
total += v;
});
console.log((total/12.0).toFixed(2));
var average = (total/12.0).toFixed(2);
angular.forEach(vm.histogram.xAxis.categories, function(v,k){
averageArray.push(average);
});
return averageArray;
}
function processChartData(data) {
var output = {};
var months = {};
var dayOfWeek = {};
var epoch = {};
angular.forEach(data, function (value, index) {
// by month
if (!months[value.eventDate.month]) {
months[value.eventDate.month] = 1;
}
months[value.eventDate.month] += 1;
// by day of week
if (!dayOfWeek[value.eventDate.dayOfWeek]) {
dayOfWeek[value.eventDate.dayOfWeek] = 1;
}
dayOfWeek[value.eventDate.dayOfWeek] += 1;
// by day
if (!epoch[value.eventDate.epoch]) {
epoch[value.eventDate.epoch] = 1;
}
epoch[value.eventDate.epoch] += 1;
});
output.months = months;
output.dayOfWeek = dayOfWeek;
return output;
}
$scope.$on('gridster-item-resized', function(item){
var element = angular.element(item.targetScope.gridsterItem.$element[0]);
vm.histogram.size = {
height: element.height()-35,
width: element.width()
};
$scope.$broadcast('highchartsng.reflow');
});
}
}
})();
The chart on the webpage looks like this with the given code!
As you can see, it shows the legend with the spline, but the spline doesn't show up. I can't figure out why.
Your calculateAverage() function returns an array of strings since .toFixed(2) returns a string. Make sure it's an array of numbers. Convert average to a number with average = parseFloat(average) for example.
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