Highchart: How to change y-axis title text inside angularjs controller? - angularjs

I have created highchart directive
App.directive('hcChart', function ($parse) {
'use strict';
return {
restrict: 'E',
replace: true
,
template: '<div><div class="chart"></div></div></div>',
link: function (scope, element, attrs) {
attrs.chart = new Highcharts.chart(element[0], {
xAxis: {
title: {
text: "Date"
},
type: 'datetime'
// labels: {
// step: 24
// }
// ,
// tickInterval: 2
},
yAxis: {
title: {
text: "Value"
}
},
dataLabels: {
enabled: true
}
,
title: {
text: ""
},
chart: {
opacity: 0.51,
backgroundColor: "white",
// plotBackgroundColor: 'rgba(0, 0, 0, 0.7)',
plotBackgroundColor: 'white',
// width: 1600,
height: 800,
zoomType: 'x',
resetZoomButton: {
position: {
x: -140,
y: 0
}
}
},
tooltip: {
crosshairs: {
width: 3,
color: 'black',
dashStyle: 'shortdot'
}
how to change y-axis title text inside controller.
As i want to show different unit for different selection.
inside controller i'm using $scope.myseries for data and $scope.categories for x-axis date time.
html code
<hc-chart id="container" categories="{{myCategories}}" series="{{mySeries}}">Placeholder for generic chart </hc-chart>
how to use $scope to update y-axis?
i tried using
$scope.yAxis[0].setTitle({text : "abc"})
but its throwing errror. not defined property.
any help please!

To change yAxis title inside angularjs controller, we need to set its property:
Highcharts.charts[0].yAxis[0].setTitle({
text: $scope.NAME
});

Related

Highchart not rendering inside a ajax function angularjs

Highchart is not rendering data from the ajax call. If i used outside $http function with static data the highchart is rendering. The high chart is not triggering.
html:
<hc-pie-chart title="Browser usage" data="pieData">Placeholder for pie chart</hc-pie-chart>
controller:
$scope.homeallpcn = function(){
var url = "homechartall";
var data = "";
$http.get(url).then( function(response) {
$scope.pieData = [{
name: "Cancelled",
y: response.c
}, {
name: "Closed",
y: response.cl,
sliced: true,
selected: true
}, {
name: "Open",
y: response.o
}, {
name: "Rejected",
y: response.r
}]
});
}
$scope.homeallpcn();
service:
mainApp.directive('hcPieChart', function () {
return {
restrict: 'E',
template: '<div></div>',
scope: {
title: '#',
data: '='
},
link: function (scope, element) {
Highcharts.chart(element[0], {
chart: {
type: 'pie'
},
title: {
text: scope.title
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: true,
format: '<b>{point.name}</b>: {point.percentage:.1f} %'
}
}
},
series: [{
data: scope.data
}]
});
}
};
})
Please give me suggestion.
Some suggestion :
1 - Do a console.log(response) after the call really show the data ?
2 - Remember pie can't works with string data so response.c, response.o and response.r must be integer or float.

Getting Error while loading data using angularjs and google charts

I am getting "All series on a given axis must be of the same data type" when loading the data.Please find the fiddle code in the below link
https://jsfiddle.net/smsh/9y5hrvne/
var app = angular.module('app', []);
app.directive('chart', function() {
return {
restrict: 'EA',
replace: true,
scope: {
data: '=data'
},
// template: '<div class="chart"></div>',
link: function(scope, element, attrs) {
var chart = new google.visualization.LineChart(element[0]);
var options = {
hAxis: {
gridlines: {
color: 'transparent'
},
format :"MMM dd",
textStyle:{
color: '#FFF',
fontName: 'Verdana',
fontSize: 11
},
showTextEvery:2
},
vAxis: {
gridlines:{
count:4,
color: '#FFF'
},
baselineColor:"#FFF",
format: '#\'%\'',
textStyle:{
color: '#FFF',
fontName: 'Verdana',
fontSize: 11
},
},
pointSize: 6,
pointShape: { type: 'circle' },
lineWidth:2,
legend: {
position: 'none'
},
backgroundColor: '#000000',
tooltip: {
textStyle: {
fontName: 'Calibri',
fontSize: 12
}
}
};
scope.$watch('data', function(v) {
var data = google.visualization.arrayToDataTable(v);
chart.draw(data, options);
});
}
};
});
app.controller('ChartController', function($scope) {
$scope.scoreHistory = [];
$scope.loadDataFromServer = function() {
var x = [
['interval', 'count','color']
];
var scoreHistory = [
{
intervalStart:new Date(2013, 5,1),
count:33,
color:'#ED1C24'
},
{
intervalStart:new Date(2013, 5,7),
count:50,
color: '#FFC90E'
},
{
intervalStart:new Date(2013, 5,8),
count:22,
color: '#ED1C24'
},
{
intervalStart:new Date(2013, 5,9),
count:45,
color: '#FFC90E'
},
{
intervalStart:new Date(2013, 5,13),
count:83,
color: '#ED1C24'
},
{
intervalStart:new Date(2013, 5,18),
count:80,
color: '#22B14C'
},
{
intervalStart:new Date(2013, 5,23),
count:100,
color: '#22B14C'
}
];
angular.forEach(scoreHistory, function(record, key) {
x.push([
record.intervalStart,
record.count,
record.color
]);
});
$scope.scoreHistory = x;
};
});
This controller i am using for getting the data and creating a angular directive to show the google line chart data in the UI.
you are getting "All series on a given axis must be of the same data type" because
$scope.scoreHistory = [["interval", "count", "color"], [Sat Jun 01 2013 00:00:00 GMT+0200 (CEST), 33, "#ED1C24"], ...]
your first element of array are your series, all strings and the rest of the elements is a data to display, don't think that the structure is right here, please check this link to have a look how this should be done.
I got the solution by doing the below code snippets:-
var x = [
['Date', 'Percentage', {'type': 'string', 'role': 'style'}]
];
var scoreHistory = [
{
intervalStart:new Date(2013, 5,1),
count:33,
color:'#ED1C24'
},

Is it possible to do a custom rendering with highchart-ng?!

I tried to use Highcharts Renderer to create my own custom shapes.
Unfortunately, I cannot find a way to invoke those methods.
Is it even possible to use Highcharts methods? with highcharts-ng?!
My Plunk
My code:
var myapp = angular.module('myapp', ["highcharts-ng"]);
myapp.controller('myctrl', function ($scope) {
$scope.chartDonut = {
options: {
chart: {
type: 'pie',
},
colors: [
'#FFFFFF',
'#AA4643',
],
credits: {
enabled: false
},
legend: {
borderWidth: 0
},
plotOptions: {
pie: {
borderWidth: 0.2,
borderColor: '#000000',
}
}
},
title: {
text: 'Browser market share, April, 2011'
},
backgroundColor: '#cccccc',
tooltip: {
formatter: function() {
return '<b>'+ this.point.name +'</b>: '+ this.y +' %';
}
},
series: [{
name: 'Browsers',
data: [{
name: 'MATCHED',
y: 25
}, {
name: 'UNMATCHED',
y: 50,
color: {
pattern: 'http://highcharts.com/demo/gfx/pattern1.png',
width: 6,
height: 6
}
}],
size: '60%',
innerSize: '56%',
showInLegend: false,
dataLabels: {
enabled: true,
connectorWidth: 0,
connectorPadding: 0,
useHTML: true,
x: 20,
formatter: function() {
if (this.point.name === 'UNMATCHED')
return '<div id="donut_unmatched">'
+ '<div id="unmatched_num">' + this.y + '</div>'
+ '<div id="unmatched_txt">' + this.point.name + '</div>'
+ '</div>';
}
}
}]
};
});
This can be done with current version, while documentation is not clear.
In source code, highcharts constructor is called:
new Highcharts.Chart(mergedOptions, func)
The second parameter is a callback when highcharts initialization is finished:
http://api.highcharts.com/highcharts#Highcharts.Chart (it does not explain its arguments)
We can get the chart object from the 1st argument of this function. Add following code to your chart config object:
func: function(chart) {
$scope.chartObj = chart;
}
Then you can use it in your view or code (for any API calls):
<span>{{chartObj.renderer.height}}</span>
$scope.chartObj.renderer.circle(...);
$scope.chartObj.getSelectedPoints();
As an example I forked the original plunk here:
http://plnkr.co/edit/6WvHEjJfr4pGqd2OvPKF?p=preview
Author here. At the moment it is not possible to do this. Pull requests gladly accepted. I'll probably add it myself in the near future.
See here to track changes: https://github.com/pablojim/highcharts-ng/issues/97
i can't find the answer either,but i've got a resolution, which is invoke the renderer in the formatter of xAxis label formatter function, and it works..

Render Two charts separate charts using angular js directives

I am trying to render two seperate charts using seperate directives for each charts, since the data is different ( also I am no expert in AngualrJs ). But only one chart was rendering to view. Please can someone help with what I have to do so that I can see both charts.Thanks.
'use strict';
angular.module('AngularApp',['AngularApp.directives']);
/*Controllers*/
var HighChartController = function HighChartController($scope) {
$scope.templateUrl = '/_layouts/AngularControls/TestController/View2.html';
$scope.type = '107';
$scope.initData = function () {
$scope.data = [
['Fire', 47.0],
['Wind', 33.0],
['Natural', 20.0]
];
}
$scope.loadChart = function () {
$scope.data1 = [60];
$scope.data2 = [40];
}
$scope.initData();
$scope.loadChart();
}
/* Directives */
angular.module('AngularApp.directives', []).
directive('drawPieChart', function () {
return function (scope, element, attrs) {
var container = $(element).attr("id");
scope.$watch('data', function () {
console.log('data');
drawPlot();
}, true);
var drawPlot = function () {
var chart;
chart = new Highcharts.Chart({
chart: {
renderTo: container,
margin: [0, 0, 0, 0],
spacingTop: 0,
spacingBottom: 0,
spacingLeft: 0,
spacingRight: 0
},
title: {
text: null
},
credits: {
enabled: false
},
tooltip: {
pointFormat: '{series.name}: <b>{point.percentage}%</b>',
percentageDecimals: 1
},
plotOptions: {
pie: {
size: '100%',
dataLabels: {
enabled: false
}
}
},
series: [{
type: 'pie',
name: 'Browser share',
data: scope.data
}]
});
}
}
});
angular.module('AngularApp.directives', []).
directive('drawBarChart', function () {
return function (scope, element, attrs) {
var container = $(element).attr("id");
scope.$watch('data', function () {
drawPlot();
}, true);
var drawPlot = function () {
var chart = new Highcharts.Chart({
chart: {
type: 'column',
renderTo: container,
marginRight: 50,
events: {
}
},
title: {
text: 'Test Scores',
style: {
color: 'black',
fontWeight: '700',
fontFamily: 'Arial',
fontSize: 20
}
},
xAxis: {
categories: [],
title: {
text: null
},
gridLineWidth: 0,
minorGridLineWidth: 0,
labels: {
style: {
color: 'black',
fontWeight: '700',
fontFamily: 'Arial',
fontSize: 11,
width: 90
}
}
},
yAxis: {
min: 0,
max: 100,
gridLineWidth: 0,
minorGridLineWidth: 0,
labels: {
enabled: false
},
title: {
text: null
}
},
tooltip: {
valueSuffix: ' million'
},
plotOptions: {
series: {
stacking: 'percent'
},
bar: {
dataLabels: {
enabled: false
}
}
},
legend: {
enabled: false,
layout: 'vertical',
align: 'right',
verticalAlign: 'bottom',
x: -40,
y: 100,
floating: true,
borderWidth: 1,
backgroundColor: '#FFFFFF',
shadow: true
},
credits: {
enabled: false
},
series: [{
name: 'null',
data: scope.data2,
borderRadius: 0,
color: "gray"
}, {
name: 'Values',
data: scope.data1,
color: "green",
borderRadius: 0
}]
});
}
}
});
Here is the markup
<div id="barChartContainer" draw-bar-chart =""></div>
</div>
<div id="pieChartContainer" draw-pie-chart="">
</div>
As Oledje mentioned, you declared the AngularApp.directives twice, but there was also an issue with how you are actually referencing the data for the charts in the directive code. I would recommended that you create an isolated scope for each directive and map the properties for the chart data in the scope definition.
So instead of
.directive('drawPieChart', function () {
return function (scope, element, attrs) {
var container = $(element).attr("id");
scope.$watch('data', function () {
console.log('data');
drawPlot();
}, true);
var drawPlot = function () {...};
};
}
You should do
.directive('drawPieChart', function () {
return {
restrict: 'E',
scope: {
chartData: "="
},
link: function (scope, element, attrs) {
scope.$watch('chartData', function (newVal,oldVal) {
if (newVal) {
drawPlot();
}
}, true);
var drawPlot = function () {
// use scope.chartData for the data
};
}
};
}
And then you also need the corresponding HTML
<draw-pie-chart chart-data="pieChartData">
And in your Controller do $scope.pieChartData=[];
Here is a jsFiddle with all of my changes: http://jsfiddle.net/callado4/9far5/5/ (look at the history to see how I progressed)
I think that your problem is that you declare a module twice.
try write not
angular.module('AngularApp.directives', []).
directive('drawPieChart'...)
angular.module('AngularApp.directives', []).
directive('drawBarChart'...)
but
angular.module('AngularApp.directives', []).
directive('drawPieChart'...).
directive('drawBarChart'...)
or
var app = angular.module('AngularApp.directives', []);
app.controller('Ctrl', ...)
app.directive('drawPieChart'...);
app.directive('drawBarChart'...);
Examples:
http://jsfiddle.net/GDQ6B/2/
http://jsfiddle.net/EYz9U/1/

AngularJS : link between directive and controller

I'm trying to call a function of my directive in my controller. I would like to reshape a curve. At the moment, I can do within the Directive. But I need to outsource the call. Do you know how can I proceed?
My directive :
.directive('drawCharts', function () {
return function (scope, element, attrs) {
scope.$watch('curveArray', function () {
drawPlot();
}, true);
var drawPlot = function () {
/* Define var for interactive chart */
var tickInterval = scope.intervalMillisecond;
var typeLine = 'line';
var chart = function (curveArrayShow, typeLine, optionLineBool, yAxisCurveArrayShow, pointStart, pointEnd) {
var optionLine = { dataLabels: { enabled: optionLineBool, y: -20 }};
new Highcharts.Chart({
chart: {
pinchType: 'x',
renderTo: 'container',
type: typeLine,
backgroundColor:'rgba(255, 255, 255, 0.95)',
events: {
load: function(event) {
//alert ('Chart loaded : ' + event);
//scope.isLoading = false;
}
}
},
legend: {
enabled: false
},
title: {
text: ''
},
xAxis: [{
type: 'datetime',
labels: {
format: '{value: <b>%d/%m</b> %H:%M}',
staggerLines: 1
},
opposite: true,
plotLines: [{
color: '#FF0000', // Red
width: 2,
value: new Date().getTime() // Position, you'll have to translate this to the values on your x axis
}],
min: pointStart,
max: pointEnd,
minPadding: 0,
maxPadding: 0,
startOnTick: false, // allow to start not from tick
endOnTick: false,
tickInterval: tickInterval
}],
yAxis: yAxisCurveArrayShow,
tooltip: {
style:{ zindex: 10 },
xDateFormat: '%d/%m %H:%M',
shared: true,
},
plotOptions: {
column: { borderWidth: 1, borderColor: '#000000' },
spline: {
marker: {
radius: 4,
lineColor: '#666666',
lineWidth: 1
}
},
series: {
dataLabels: {
enabled: optionLineBool,
style: {font: 'bold 11px Arial', textShadow: '0 0 3px white, 0 0 3px white'}
},
marker: {
lineColor: null,
radius: 6,
states: {
hover: {
radius: 10
}
}
}
},
line: optionLine
},
series: curveArrayShow
}}
var pointStart = scope.intervalResearchTime.startDateTime + scope.intervalMillisecond; //remove padding that adding for serie type column
var pointEnd = scope.intervalResearchTime.endDateTime - scope.intervalMillisecond; //remove padding that adding for serie type column
chart(scope.curveArray, typeLine, false, scope.yAxisCurveArray, pointStart, pointEnd);
}
};
In my controller i need to update my chart. So i would like to call the function :
$scope.redrawCurve = function(_index) {
/* My algorithm ...... */
chart(curveArrayShow, typeLine, false, $scope.yAxisCurveArray, pointStart, pointEnd);
};
Thx,
Alex
My suggestion is to use event to notify the directive to redraw the plot, like this:
Controller:
$scope.redrawCurve = function(_index) {
/* My algorithm ...... */
$scope.$broadcast('redraw', arg1, arg2, /* other necessary arguments */);
};
Directive:
scope.$on('redraw', function(arg1, arg2, /* other necessary arguments */) {
drawPlot();
});

Resources