Data binding and promise in AngularJS - angularjs

I have the following factory I use to return a http promise with the user data from the server
(function () {
angular.module('BlurAdmin.theme')
.factory('getData', function($http){
var service = {};
service.objData = null;
service.savePromise = function(objData) {
service.objData = objData;
}
service.getSavedPromise = function() {
return service.objData;
}
service.getDataFromServer = function() {
var promise = $http.get('/admin/data');
service.savePromise(promise);
}
return service;
});
})();
I launch this http request at the run method of the app.
In another controller I have done the following
getData.getSavedPromise().then(function (data) {
$scope.newVisits = data.data.data.newVisitors;
});
var pieColor = baUtil.hexToRGB(baConfig.colors.defaultText, 0.2);
$scope.charts = [{
color: pieColor,
description: 'New Visits',
stats: '$ ' + $scope.newVisits,
icon: 'person',
}, {
color: pieColor,
description: 'Purchases',
stats: '$ 89,745',
icon: 'money',
}, {
color: pieColor,
description: 'Active Users',
stats: '178,391',
icon: 'face',
}, {
color: pieColor,
description: 'Returned',
stats: '32,592',
icon: 'refresh',
}
];
The Data structure is a little messed up and I need to fix it but that is beside the point.
I use for example
<div class="description-stats">{{ ::chart.stats }}</div>
In the html.
The issue is that the data is not being bind and I see undefined in the page.
What am I doing wrong?

Related

Highcharts graph does not update with firebase

$scope.hhData = $firebaseArray(aRef.orderByChild('ts').startAt('2018-07-02').limitToLast(50));
$scope.hhData.$loaded().then(function () {
$scope.chartSeriesYArray = [];
$scope.chartSeriesXArray = [];
$scope.hhData.$watch(function() {
angular.forEach($scope.hhData, function (value) {
$scope.chartSeriesXArray.push(moment(value.ts).format('MMMM Do YYYY, h:mm:ss'));
$scope.chartSeriesYArray.push(parseFloat(value.ein));
});
Highcharts.chart('chart', {
chart: {
type: 'column'
},
title: {
text: 'Half Hourly Energy Consumption'
},
xAxis: {
categories: $scope.chartSeriesXArray,
crosshair: true
},
yAxis: {
min: 0,
title: {
text: 'Energy (kwh)'
}
},
series: [{
name: 'Meter01',
data: $scope.chartSeriesYArray
}]
});
});
});
I wanted to be able to update the data live from Firebase into the chart. However, this code only allows the data to be updated once at the start and it never updates itself again. Is there any way to work around this? - tried the $interval method as suggested but it didn't work :(
Update: I managed to do so with $watch. However, this now means that my graph will only show when there is data coming in. If there is no data coming in (EG: when you just turn on the system) then no graph will show at all. This there another way around this
Try using the $interval service to retrieve your data after a certain amount of time.
$interval(function() {
$scope.hhData.$loaded().then(function () {
$scope.chartSeriesYArray = [];
$scope.chartSeriesXArray = [];
angular.forEach($scope.hhData, function (value) {
$scope.chartSeriesXArray.push(moment(value.ts).format('MMMM Do YYYY, h:mm:ss'));
$scope.chartSeriesYArray.push(parseFloat(value.ein));
});
Highcharts.chart('chart', {
chart: {
type: 'column'
},
title: {
text: 'Half Hourly Energy Consumption'
},
xAxis: {
categories: $scope.chartSeriesXArray,
crosshair: true
},
yAxis: {
min: 0,
title: {
text: 'Energy (kwh)'
}
},
series: [{
name: 'Meter01',
data: $scope.chartSeriesYArray
}]
});
});
}, 5000); //this function will run every 5 seconds
*don't forget you also need to add the $interval parameter to your controller, and the interval goes by milliseconds
app.controller('myCtrl',["$scope", "$interval", function($scope, $interval) {
//code goes here
}]);

Display highcharts graph with a lot of data in angularjs

I have an angularjs application and I use highcharts-ng to display some graphs. I got the data from an http request and I modify the data to display them in the graph.
If I receive just a just some data, it's ok, it works but when I receive a lot of data, the highcharts component take a long time to display the data. And in this time the browser in freezed.
In my controller, I have:
widgetCtrl.chartDataLine = {
chart: {
type: 'spline',
zoomType: 'xy'
},
title: {
text: 'Power Consumption'
},
xAxis: {
type: 'datetime',
title: {
text: 'Date time'
}
},
yAxis: {
title: {
text: 'Power (W)'
},
min: 0
},
options: {
exporting: {
enabled: true,
allowHTML: true,
buttons: {
contextButton: {
menuItems: null,
onclick: function () {
this.exportChart();
}
}
}
}
},
plotOptions:{
series:{
turboThreshold:60000 // larger threshold or set to 0 to disable
}
},
series: []
};
I call the data like that:
var getMetrics = function (searchText) {
var param = {
target: searchText
};
xcsDatasource.get('beo').callAction('getPowerMetrics', param.target, widgetCtrl.pickerFrom.date, widgetCtrl.pickerTo.date).then(
function (result) {
widgetCtrl.metrics = result;
widgetCtrl.metricsAsString = JSON.stringify(result);
var t = getChartData(result);
widgetCtrl.chartDataLine.series = angular.copy(t);
console.log(widgetCtrl.chartDataLine);
//widgetCtrl.chartDataArea.series = getChartData(result);
},
function () {
widgetCtrl.metrics = {};
widgetCtrl.metricsAsString = '';
}
);
};
And this is my html:
<div ng-if="config.linechart" class="graph-container col-sm-12">
<highchart id="chart1" config="pwrDashboardViewCtrl.chartDataLine"></highchart>
</div>
Do you have an idea how I can do to continue to load the grapph without freezing the browser ?

Highstock Navigator Displayed Twice

I am using highstock,5.0.10 with angularJS.
In my chart navigator got displayed twice, like below
As you can see, navigator has been rendered twice. However, if you refresh the page, everything looks fine.
Any ideas?
I have added my Highstock code here.
Highcharts.stockChart('FindComputerUsage', {
rangeSelector: {
selected: 1
},
credits: {
enabled: false
},
title: {
text: ''
},
yAxis: {
title: {
text: 'Percentage of time (%) '
}
},
tooltip: {
formatter: function() {
var date = new Date(requiredData[this.points[0].point.index][0]);
return date + '<br>' + 'Percentage:' + requiredData[this.points[0].point.index][1] + '%';
}
},
series: [{
name: 'Percentage (%)',
data: requiredData,
tooltip: {
valueDecimals: 2,
}
}],
lang :{
noData : "No data to display "
}
});
Here you can see a working example: https://plnkr.co/edit/OphM9wf8WyGm8U6HXfTy
You haven't show your HTML view, but I guess it's similar to this.
<div ng-controller="demoCtrl">
<div id="container" style="height: 400px; min-width: 310px"></div>
</div>
Concerning controller scope, I didn't change anything:
var app = angular.module('demoApp', []);
app.controller('demoCtrl', function($scope){
$scope.data = [
[1290729600000,45.00],
[1290988800000,45.27],
[1291075200000,44.45]
];
Highcharts.stockChart('container', {
rangeSelector: {
selected: 1
},
title: {
text: 'Qing Xu Example'
},
series: [{
name: 'Value',
data: $scope.data,
tooltip: {
valueDecimals: 2
}
}]
})
});

angularJS service object property undefined

I have a controller using a service chartFactory.chartData property to give some data to view. The problem is that the factory is returning the object before the chartFactory.chartData function has time to return the data from the back end, so the property is undefined.
I understand this is an async issue, but I'm not sure how to handle it between a factory and a controller.
chartFactory.js
app.factory('chartFactory', ['$http', '$interval', function($http, $interval) {
var service = {
get chartData() {
$http.get('/portfolio/get-chart-data')
.then(function(response) {
console.log(response.data, 'response data') //logging after undefined message
return response.data
})
}
}
return service
}])
chartController.js
app.controller('chartCtrl', function($scope, $timeout, $http, chartFactory) {
$scope.chartData = chartFactory
$scope.height_chart = window.innerHeight * 0.4
$scope.labels = chartFactory.chartData[0]; //undefined
$scope.series = chartFactory.chartData['GDAX Value']; //undefined
$scope.data = [
chartFactory.chartData[1] //undefined
];
$scope.onClick = function(points, evt) {
console.log(points, evt);
};
$scope.datasetOverride = [{
yAxisID: 'y-axis-1'
}];
$scope.options = {
responsive: true,
maintainAspectRatio: false,
scales: {
yAxes: [{
id: 'y-axis-1',
// type: 'linear',
display: true,
position: 'left',
ticks: {
beginAtZero: false,
callback: function(value, index, values) {
if (parseInt(value) >= 1000) {
return '$' + value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
} else {
return '$' + value;
}
}
}
}],
xAxes: [{
display: false
}]
}
}
})
Change your controller as,
chartFactory.chartData().then(function(response) {
$scope.labels = getchartData .response.data[0];
$scope.series = chartFactory.response.data['GDAX Value'];
});

How to use react render with AngularJs and ngReact

I am trying to use StormReact library in angularJs app.
In below code i have created class inside the library which is bundled using webpack as single bundle.js
window.HelloStormReact = React.createClass({
render: function() {
var Engine = require("../src/Engine")();
var model = {links:[],nodes: []};
function generateSet(model,offsetX,offsetY){
var node1 = Engine.UID();
var node2 = Engine.UID();
var node3 = Engine.UID();
var node4 = Engine.UID();
var node5 = Engine.UID();
model.links = model.links.concat([
{
id: Engine.UID(),
source: node1,
sourcePort: 'out',
target: node2,
targetPort: 'in',
},
{
id: Engine.UID(),
source: node1,
sourcePort: 'out',
target: node3,
targetPort: 'in'
},
{
id: Engine.UID(),
source: node2,
sourcePort: 'out',
target: node4,
targetPort: 'in'
},
{
id: Engine.UID(),
source: node4,
sourcePort: 'out',
target: node5,
targetPort: 'in2'
},
{
id: Engine.UID(),
source: node2,
sourcePort: 'out',
target: node5,
targetPort: 'in'
}
]);
model.nodes = model.nodes.concat([
{
id:node1,
type: 'action',
data: {
name: "Create User",
outVariables: ['out']
},
x:50 + offsetX,
y:50 + offsetY
},
{
id:node2,
type: 'action',
data: {
name: "Add Card to User",
inVariables: ['in','in 2'],
outVariables: ['out']
},
x:250 +offsetX,
y:50 + offsetY
},
{
id:node3,
type: 'action',
data: {
color: 'rgb(0,192,255)',
name: "Remove User",
inVariables: ['in']
},
x:250 + offsetX,
y:150 + offsetY
},
{
id:node4,
type: 'action',
data: {
color: 'rgb(0,192,255)',
name: "Remove User",
inVariables: ['in'],
outVariables: ['out']
},
x:500 + offsetX,
y:150 + offsetY
},
{
id:node5,
type: 'action',
data: {
color: 'rgb(192,255,0)',
name: "Complex Action 2",
inVariables: ['in','in2','in3']
},
x:800 + offsetX,
y:100 + offsetY
},
]);
}
generateSet(model,0,0);
Engine.registerNodeFactory({
type:'action',
generateModel: function(model){
return React.createElement(BasicNodeWidget,{
removeAction: function(){
Engine.removeNode(model);
},
color: model.data.color,
node: model,
name: model.data.name,
inPorts: model.data.inVariables,
outPorts: model.data.outVariables
});
}
});
Engine.loadModel(model);
return ReactDOM.render(React.createElement(Canvas,{engine: Engine}), document.getElementById("howdy"));;
}
});
In index.html, I used that class created in Storm react library module.
<div class="content">
<react-component name="HelloStormReact" />
<div class="storm-flow-canvas" id="howdy">
</div>
</div>
I am getting the error
Constructor.render(): A valid React element (or null) must be returned.
You may have returned undefined, an array or some other invalid object.
Help me to write correct render object to return.
Since HelloStormReact is just a component, in its render function, you don't need to render it again, just return React.createElement(Canvas,{engine: Engine}) in the render function.

Resources