Getting Error while loading data using angularjs and google charts - angularjs

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'
},

Related

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

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
});

Highcharts-ng, excessive re rendering

I wonder how I should go about having better animations when adding points to a area plot. In regular highcharts this is done pretty smooth but using highcharts-ng it rerenders a huge chunk of the chart.
I have two fiddels that shows the issue. Maby there is a simple way to solve this ?
Highcharts-ng
http://jsfiddle.net/Cp73s/3399/
var myapp = angular.module('myapp', ["highcharts-ng"]);
myapp.controller('myctrl', function ($scope) {
$scope.addPoints = function () {
var seriesArray = $scope.highchartsNG.series
var rndIdx = Math.floor(Math.random() *10+7);
$scope.highchartsNG.series[0].data.push(rndIdx);
};
$scope.highchartsNG = {
options: {
chart: {
type: 'area'
},
plotOptions: {
area: {
fillOpacity: 0.15,
dataLabels: {
allowOverlap: true,
enabled: true,
padding: 0,
style: {
fontSize: '25px'
}
},
enableMouseTracking: true
}
},
},
series: [{
data: [10, 15, 12, 8, 7]
}]
}
});
Regular-highcharts
http://jsfiddle.net/m8Lavyrc/3/
$(function () {
$('#container').highcharts({
chart: {
type: 'area'
},
plotOptions: {
area: {
fillOpacity: 0.15,
dataLabels: {
allowOverlap: true,
enabled: true,
padding: 0,
style: {
fontSize: '25px'
}
},
enableMouseTracking: true
}
},
series: [{
data: [10, 15, 12, 8, 7]
}]
});
// the button action
var i = 0;
$('#button').click(function () {
var chart = $('#container').highcharts();
chart.series[0].addPoint(Math.floor(Math.random() *10+7));
});
});
Tnx

Flot Chart - Graphic data as an object array with multiple attributes

I would like to have an array object instead of the following json format;
[1409558400000, 7.45],[1409562000000, 5.71], [1409565600000, 7.50],
... .;
My purpose is to show all data on the graph based on their hh:mm parameter (which is done in the link already), and I ended up such json array;
[10, 7.45],[09, 5.71], [11, 7.50], ...
But I also would like to keep their timestamp in order to have more information about each data point so that I can provide the timestamp when user clicks on a point.
I simply need to have something like this [10, 7.45,1409562000000] ; hour value, age, and timestamp respectively.
How can I have such data array for flot chart ?
var d = [
[1409558400000, 7.45],
[1409562000000, 5.71],
[1409565600000, 7.50],
[1409569200000, 7.63],
[1409576400000, 3.14],
[1409644800000, 7.45],
[1409648400000, 5.71],
[1409652000000, 7.50],
[1409655600000, 7.63],
[1409662800000, 3.14],
[1409731200000, 7.45],
[1409734800000, 5.71],
[1409738400000, 7.50],
[1409742000000, 7.63],
[1409749200000, 3.14]
];
$.each(d, function (index, datapoint) {
datapoint[0] = (new Date(datapoint[0])).getHours();
});
$.plot("#placeholder", [d], {
series: {
lines: {
show: true
},
points: {
show: true
}
},
grid: {
hoverable: true,
clickable: true,
markings: [{
yaxis: {
from: 0,
to: 4
},
color: "#F2CDEA"
}, {
yaxis: {
from: 4,
to: 7
},
color: "#D7EEE1"
}, {
yaxis: {
from: 7,
to: 12
},
color: "#F2CDEA"
}]
},
xaxis: {
},
yaxis: {
min: 0,
max: 12
}
});
$("#placeholder").bind("plotclick", function(event, pos, item) {
var x = item.datapoint[0].toFixed(2),
y = item.datapoint[1].toFixed(2);
if (item) {
//window.location="pagex.html";
alert("x: " + x);
//plot.highlight(item.series, item.datapoint);
}
});
<!-- basic time series flot chart -->
<h>Create a custom green range</h>
<div style="height: 400px; width: 600px;" id="placeholder"></div>
http://jsfiddle.net/shamaleyte/wzLaqzf5/1/
Basically I adapt the answer given in the following link for my scenario.
Link for Referenced answer
Link : displaying custom tooltip when hovering over a point in flot
My Code:
var data = [
[1409558400000, 7.45],
[1409562000033, 5.71],
];
$.each(data, function (index, datapoint) {
datapoint[2] = datapoint[0]; // copy the timestamp and paste it as the 3rd object
datapoint[0] = (new Date(datapoint[0])).getHours(); // to put hours on y axis
});
$.plot("#placeholder", [d2], {
series: {
lines: {
show: true
},
points: {
show: true
}
},
grid: {
hoverable: true,
clickable: true,
markings: [{
yaxis: {
from: 0,
to: 4
},
color: "#F2CDEA"
}, {
yaxis: {
from: 4,
to: 7
},
color: "#D7EEE1"
}, {
yaxis: {
from: 7,
to: 12
},
color: "#F2CDEA"
}]
},
xaxis: {
},
yaxis: {
min: 0,
max: 12
}
});
$("#placeholder").bind("plotclick", function(event, pos, item) {
var x = item.datapoint[0].toFixed(2),
y = item.datapoint[1].toFixed(2);
var tooltip = item.series.data[item.dataIndex][2];
if (item) {
//window.location="pagex.html";
alert("x: " + tooltip);
//plot.highlight(item.series, item.datapoint);
}
});
My Fiddle : http://jsfiddle.net/shamaleyte/wzLaqzf5/2/

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