I'm trying to use high charts via angular to take advantage of double binding. I'm having an issue rendering the data, the graph works but the data is not showing up in the chart. When I check the DOM console I can get the array but for some reason its not showing up in the graph.
cpvmPartners = [];
cpvmPlannedCpm = [];
actualCpm = [];
graphData = [];
cpvm = [];
plannedPrepared = [];
getData = function(){
$.getJSON('/cpvmdata', function(data) {
for(k in data){
if(data[k]['audience'] == 'GCM'){
graphData.push([data[k]['partner'],data[k]['plannedcpm']])
actualCpm.push(Math.round((data[k]['mediacost']/data[k]['impressions']*1000)))
cpvmPlannedCpm.push(data[k]['plannedcpm'])
cpvmPartners.push(data[k]['partner'])
}
}
});
}
prepareData = function(){
for(var i = 0; i < actualCpm.length; i++) {
actualPrepared.push({name: "CPM", data: actualCpm[i]})
plannedPrepared.push({name: "Planned CPM", data: cpvmPlannedCpm[i]})
}
}
myApp = angular.module('main', ['highcharts-ng']);
myApp.controller('graphController', function ($scope) {
getData();
prepareData();
$scope.highchartsNG = {
options: {
chart: {
type: 'bar'
}
},
series: [{
data: actualCpm
}],
title: {
text: 'Hello'
},
loading: false
}
});
So the getData() function you call in the angular controller is asynchronous:
By the time you have gotten the data, you have already made your chart in $scope.highChartNg
That is why you can see your data the console but you don't actually set it to the actualCpm by the time angular is done. To fix this you need to create the chart IN your $.getJSON function like so:
var options = {
chart: {
renderTo: 'container',
type: 'spline'
},
series: [{}]
};
$.getJSON('data.json', function(data) {
options.series[0].data = data;
var chart = new Highcharts.Chart(options);
});
You can see more here: http://www.highcharts.com/docs/working-with-data/custom-preprocessing
Easier just to use
$http.get
Angular service.
Blending jQuery and Angular is troublesome for scoping.
$http.get('cpvmdata')
.then(function(response){
$scope.output = response.data;
for(k in $scope.output){
if($scope.output[k]['audience'] == 'GCM'){
$scope.planned.push($scope.output[k]['plannedcpm'])
$scope.partners.push($scope.output[k]['partner'])
$scope.cpm.push(Math.round(($scope.output[k]['mediacost']/$scope.output[k]['impressions']*1000)))
}
}
});
Related
I'm trying to figure out how to update a chart.js chart. Google's returned with a lot of answers and I think some are outdated because I can't seem to get any of the solutions to work. The documentation page says just use chartname.update() but it doesn't seem to work for me. I already checked console to make sure the chart object was updating. For some reason the chart itself on the page just isn't changing.
let chartContainer = document.getElementById('charts');
let overview = {
create: function () {
let chartCanvas = document.createElement('canvas');
chartCanvas.id = 'overviewChart';
chartCanvas.appendChild(document.createTextNode('test'));
chartContainer.appendChild(chartCanvas);
let overviewChart = document.getElementById('overviewChart').getContext('2d');
renderChart = new Chart(overviewChart, {
type: 'bar',
data: {
labels:subjectList,
datasets: [{
barThickness: 'flex',
label: 'Completed Credits',
data: []
}]
},
options: {
}
})
},
reload: function() {
console.log('reloaded overview chart');
renderChart.data.datasets.data = [];
for (subject in classes) {
console.log('adding: ' + classes[subject].count)
renderChart.data.datasets.data.push(classes[subject].count);
}
renderChart.update();
}
}
function reloadCharts() {
overview.reload();
}
overview.create();
There are problems in your reload function where you access renderChart.data.datasets.
Please note that renderChart.data.datasets is an array. Therefore, you need to make the following changes:
reload: function() {
// renderChart.data.datasets.data = []; // old
renderChart.data.datasets[0].data = []; // new
for (subject in classes) {
console.log('adding: ' + classes[subject].count)
// renderChart.data.datasets.data.push(classes[subject].count); // old
renderChart.data.datasets[0].data.push(classes[subject].count); // new
}
renderChart.update();
}
I used the following code to fetch JSON data which was a success. I initialized a global array and stored one unit of that data in an array. Now somewhere in my code, there is an array nested inside an object how do I pass this array there?
var myRequest = new Request("https://script.googleusercontent.com/macros/echo?user_content_key=KW75vuIX25SoStm_K2HLVQNBRF2fx_5URDdL-vYJfUSTBaOAlMkJeWc25wjo5zdMLaznziyuqNd4B5kNs8k3tH0OxgnfssPwm5_BxDlH2jW0nuo2oDemN9CCS2h10ox_1xSncGQajx_ryfhECjZEnIFtsXaNuh0rFflir-T-GWuA8AvQ2kUI-jEwpZssg8RaEHh5W9MAfgDGMRkNsN06wEWY2nZ7HPw5&lib=M_p61mp1Qy6uGkXTBzlj4kloBXIZCdEN3")
fetch(myRequest)
.then(function(res){
return res.json();
})
.then(function(data){
for(var i=0;i<400;i++)
{
arr[i]=data.user[i].battingScore;
}
return arr;
});
This is where I want to use the arr:
document.addEventListener('DOMContentLoaded', function () {
document.addEventListener('DOMContentLoaded', function () {
var myChart3 = Highcharts.chart('c', {
title: {
text: 'Logarithmic axis demo'
},
xAxis: {
tickInterval: 1,
type: 'logarithmic'
},
yAxis: {
type: 'logarithmic',
minorTickInterval: 0.1
},
tooltip: {
headerFormat: '<b>{series.name}</b><br />',
pointFormat: 'x = {point.x}, y = {point.y}'
},
series: [{
data:[], //here
pointStart: 1
}]
});
});
});
Note: Here, series is an array of objects but is an attribute of hello object. I want the values of arr inside data which is an array. How to do that?
If you want to gather the data before rendering the chart, you could do this.
fetch(myRequest)
.then(function(res){
return res.json();
})
.then(function(data){
for(var i=0;i<400;i++){
arr[i]=data.user[i].battingScore;
}
return arr;
})
.then(function(scores){
document.addEventListener('DOMContentLoaded', function () {
var myChart3 = Highcharts.chart('c', {
. . .
series: [{
data:scores,
pointStart: 1
}]
});
});
});
});
Otherwise, you can define your myChart3 as a global variable and change "var myChart3=" to just "myChart3=" in your event listener. Then, you can populate the data into the existing chart using series.addPoint like this:
var myChart3;
document.addEventListener('DOMContentLoaded', function () {
myChart3 = Highcharts.chart('c', {
. . .
});
});
fetch(myRequest)
.then(function(res){
return res.json();
})
.then(function(data){
for(var i=0;i<400;i++){
myChart3.series[0].addPoint(data.user[i].battingScore, false);
}
myChart3.redraw();
},
cache: false
});
I have a chart, using angular-chart.js, which the x and y axis values varies depending on which item a user clicks on. When one of the items is clicked, it omits the first unit so instead of displaying 2.52 it displays .52. If you see below, the log is showing the correct information, just not displaying it.
The website I have provided a link to above provides examples which I have followed and I am a bit stumped why this is happening. It is quite lengthy my code for populting the chart with the correct data but I will try and provide only the necessary code.
Any ideas why the correct value isn't being displayed in the Y axis?
service which gathers the data for the graph
app.factory('loadPatentItemService', ['$http', '$timeout', function($http, $timeout) {
var factory = {};
var selectedData = null;
var selectedLabel = null;
var selectedItem = null;
var REST_SERVICE_URI = '../json/cost-data.json';
//function is invoked from the view and data is passed depending which item was clicked
factory.select = function(item) {
selectedItem = item;
factory.getPatent();
return [selectedItem];
}
factory.getPatent = function() {
var itemId = [];
itemId.push(selectedItem.id)
$http.get(REST_SERVICE_URI)
.then(function(response){
var items = response.data.dataset;
var graphData = [];
var graphLabel = [];
for (i = 0;i < items.length; i++) {
if(items[i].id == itemId) {
graphData.push(items[i].data);
graphLabel.push(items[i].label);
factory.graphLabel(graphLabel);
factory.graphData(graphData);
}
}
}),
function(errResponse) {
console.log('error')
}
return selectedItem;
}
factory.graphData = function(data) {
selectedData = data;
return [data];
}
factory.graphLabel = function(label) {
selectedLabel = label;
return [label];
}
factory.getData = function() {
return selectedData;
}
factory.getLabel = function() {
return selectedLabel;
}
return factory;
}])
graph controller
app.controller("lineCtrl", ['$scope', '$timeout', 'loadPatentItemService', function ($scope, $timeout, loadPatentItemService) {
var initGraph = loadPatentItemService.getPatent();
var getGraphData = loadPatentItemService.getData();
var getGraphLabel = loadPatentItemService.getLabel();
$scope.labels = getGraphLabel[0];
$scope.data = getGraphData[0];
console.log(getGraphData[0], getGraphLabel[0])
$scope.datasetOverride = [{ yAxisID: 'y-axis-1' }, { yAxisID: 'y-axis-2' }];
$scope.options = {
scales: {
yAxes: [
{
id: 'y-axis-1',
type: 'linear',
display: true,
position: 'left'
},
{
id: 'y-axis-2',
type: 'linear',
display: true,
position: 'right'
}
]
}
};
}])
I'm using Angular-nvD3. I have a simple chart that looks like this:
HTML:
<nvd3 options="options" data="data"></nvd3>
JS:
$scope.options = {
chart: {
type: 'pieChart',
height: 450,
x: function (d) { return d.key; },
y: function (d) { return d.y; },
showLabels: true,
duration: 1100,
showLegend: false
}
};
My data object is just a simple array of objects with key and y properties. On some DOM event, I update the data from the server and change the data object. When I do this, my chart is resized.
Why is this happening and how can I prevent it?
Update:
// This is the function that is called on the DOM event.
var loadAllData = function () {
var result = getData();
result.$promise.then(function (returnedAmounts) {
loadChartsData(returnedAmounts.expenses, $scope.data);
}, function (error) {
// Error.
});
}
var loadChartsData = function (group, chartsData) {
// Iterate over the group
for (var i = 0; i < group.length; i++) {
chartsData[i] = {
key: group[i].name || group[i].key,
y: group[i].amount
};
}
}
try to set your config.deepWatchData = false, that way the chart will only update when you tell it to. (by using api.refresh)
I need parse the enclosure tag in order to get the url image. It's assumed I should get the MIXED OUTPUT with the json+xml code but I get a undefined value from the enclousure tag when I try parse it. I'm doing this like I saw at this post > Google Feed Loader API ignoring XML attributes < .In addition I tried to get the MIXED format writing the url manually but It doesn't work. There is my whole code. How could I know that Im getting the mixed json output?
var feeds = [];
var entryImageUrl = [];
angular.module('starter.controllers', ['ngResource','ngLocale'])
.factory('FeedLoader', function ($resource) {
return $resource('http://ajax.googleapis.com/ajax/services/feed/load', {}, {
fetch: { method: 'JSONP', params: {v: '1.0', callback: 'JSON_CALLBACK', output: 'json_xml'} }
});
})
.service('FeedList', function ($rootScope, FeedLoader) {
this.get = function() {
var feedSources = [
{title: 'Heraldo De Barbate', url: 'http://www.heraldodebarbate.es/rss/last'},
];
if (feeds.length === 0) {
for (var i=0; i<feedSources.length; i++) {
FeedLoader.fetch({q: feedSources[i].url, num: 10}, {}, function (data) {
var feed = data.responseData.feed;
**var entryImageUrl = feed.xmlNode.getElementsByTagName("enclosure")[i].getAttribute("url");**
feeds.push(feed);
});
}
}
return feeds;
};
})
.controller('FeedCtrl', function ($scope, FeedList,$timeout) {
$scope.update = function(){
$scope.feeds = FeedList.get();
$scope.$on('FeedList', function (event, data) {
$scope.feeds = data;
// $scope.entryImageUrl
console.log(feeds);
});
$timeout(function() {
$scope.$broadcast('scroll.refreshComplete');
}, 500);
}
})
How could I know that Im getting the mixed json output?
Use a test for tags within JSON:
function testMe(node)
{
return /</.test(JSON.stringify(node) )
}
then run it on the feed:
var mixed_format = testMe(feed);
and call another function which parses the data:
if (mixed_format)
{
mixed_parser(feed)
}
else
{
json_parser(feed)
}