I am using a factory in angular.js and $http.get method to grab and process JSON data. The JSON data seems successfully parsed into factory, but I have problem access property of this JSON data.
Here is my js code:
var app = angular.module("app", []);
app.factory('mainInfo', function($http) {
var obj = {content:null};
//the php will return json data below
$http.get('http://localhost/test.php').success(function(response){
obj.content = response.records;
});
return obj;
});
app.controller('Ctrl', function($scope, mainInfo){
$scope.foo = mainInfo.content;
}) ;
Now if I try to access foo within Ctrl
controller, the webpage will display no data:<div ng-controller="Ctrl">Controller: {{foo}}</div>
However, if I change to $scope.foo = mainInfo
in the Ctrl
, then the webpage will display correctly the JSON data.
May I know what is the proper way to access mainInfo.content
property in Ctrl
controller?
The reason why I need to access JSON property is because I need to pre-process the data. I intend to use these data in a Chart, as in below controller. Currently this controller is not working either, because I have the same problem accessing JSON property as in the Ctrl
controller.
app.controller("LineCtrl", function ($scope, mainInfo) {
var timePoints = [];
var percentagePoints = [];
var i = 0;
for( i = 0; i < mainInfo.content.length; i ++) {
timePoints.push(mainInfo.content[i].Time);
percentagePoints.push(mainInfo.content[i].Percentage);
}
$scope.labels = timePoints;
$scope.data = percentagePoints;
$scope.onClick = function (points, evt) {
console.log(points, evt);
};
});
The json data:
{
"records": [
{
"Id": "1",
"Time": "2015-07-25 08:00:00",
"Percentage": "60"
},
{
"Id": "2",
"Time": "2015-07-25 09:00:00",
"Percentage": "70"
},
{
"Id": "3",
"Time": "2015-07-25 10:00:00",
"Percentage": "80"
}
]
}
With regards to the factory-controller communication, I am just referring the solution from another post: reference
$http.get returns a promise -- your problem is that you are returning "obj" immediately, and your controller tries to access the data before the $http.get promise is resolved.
use $http like so (no need to use $q.defer() as shown in the other comment):
var app = angular.module("app", []);
app.factory('mainInfo', function($http) {
var getRecordsPromise = $http.get('http://localhost/test.php').then(function(response){
//whatever is returned here will be accessible in the .then that is chained
return response.data.records;
});
return {
getRecords: getRecordsPromise
};
});
app.controller('Ctrl', function($scope, mainInfo){
mainInfo.getRecords.then(function (records) {
$scope.foo = records;
});
}) ;
Try this instead
var obj = {content: []};
obj.$promise = $http.get('http://localhost/test.php').then(function(response) {
angular.copy(response.data.records, obj.content);
return response.data;
});
return obj;
The reason your former method didn't work was because you were re-assigning the content
property of obj
, thus destroying any previous references.
This is also why using $scope.foo = mainInfo
worked because the reference to obj
(via mainInfo
) was maintained.
Using angular.copy
maintains the previous reference whilst populating the data.
That should take care of references in the template that get updated when the $http
promise resolves (due to $http
triggering a digest cycle). For accessing the data in your controller, use the $promise
property
$scope.foo = mainInfo.content;
mainInfo.$promise.then(function(data) {
// access data.records here
});
Maintaining the data inside your factory is a good idea if you share your factory with multiple consumers (eg controllers). They may all reference mainInfo.content
and mainInfo.$promise
and all will be accessing the same data set.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With