Reputation: 582
in my angular app I use a factory which get json data and pass it to a controller. it is working for me if I use simple json array but fails in a nested array in case of a simple json file I have this structure
[
{
"name": "bond_1",
"profession": "Programmer",
"hometown": "St Louis, MO"
},
{
"name": "bond_2",
"profession": "Salesman",
"hometown": "Denver, CO"
},
{
"name": "bond_3",
"profession": "CEO",
"hometown": "San Francisco, CA"
}
]
my factory is this
.factory('Topology', function ($http){
var data = [];
return{
get: function(){
if (data.length == 0){
$http.get("data.json")
.success(function (response){
for(var i=0, ii=response.length; i<ii; i++){
data.push(response [i]);
}
});
}
return data;
},
}
});
and my controller is this
var installerControllers =angular.module('installerControllers', []);
installerControllers.controller('stageThreeCtrl', function ($scope, Topology) {
$scope.bonds=Topology.get();
})
now it all working fine and I can view the data when I doing ng-repeat on it from the view
but i need instead of the simple json structure use a nested array which looks like this
{
"bonds":[
{
"name": "Alex",
"profession": "Programmer",
"hometown": "St Louis, MO"
},
{
"name": "David",
"profession": "Salesman",
"hometown": "Denver, CO"
},
{
"name": "Laura",
"profession": "CEO",
"hometown": "San Francisco, CA"
}
],
"networks":[
{
"name": "test",
"all_hosts": "false",
"IP_Version": "IPV4",
"IP address": "10.10.10.10",
"IPV net mask": "255.255.255.0",
"Interface": "bond 0",
"VLAN TAG": "4001",
"Description": "some custom description"
}
]
}
now I am trying to call for one of the objects from the controller in this way
var installerControllers =angular.module('installerControllers', []);
installerControllers.controller('stageThreeCtrl', function ($scope, Topology) {
var data=Topology.get();
$scope.bonds=data.bonds;
})
but it is not working and I got in the console.log an empty array
your help will be very appreciated
Upvotes: 1
Views: 1452
Reputation: 95017
Your problem is NOT an asynchronous problem, you simply aren't referencing your new data format properly. I've substituted the $http
call with a $timeout
since I don't have a server to test against that returns your data. Since your data format has changed, you need to change the way you're referencing it in the factory, controller, and view.
var app = angular.module('app', []).factory('Topology', function ($timeout){
var data = {}; // no longer an array
return{
get: function(){
if (!data.bonds){
$timeout(function () {
data.bonds = [{name: 'Hello World!'}]; // this would be response.bonds
data.networks = [{name: 'Hello World!'}]; // this would be response.networks
}, 2000);
}
return data;
},
}
}).controller('stageThreeCtrl', function ($scope, Topology) {
var data=Topology.get();
$scope.data = data; // renamed to data
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<p>wait 2 seconds...</p>
<ul ng-controller="stageThreeCtrl">
<li ng-repeat="bond in data.bonds">{{bond.name}}</li> <!-- using data.bonds -->
</ul>
</div>
A better alternative would be to do some minor restructuring to instead take advantage of the promise returned from $http
.
var app = angular.module('app', []).factory('Topology', function ($http){
var promise;
return{
get: function(){
if (!promise){
promise = $http.get("data.json");
}
return promise;
},
}
}).controller('stageThreeCtrl', function ($scope, Topology) {
Topology.get().then(function (response) {
$scope.bonds = response.data.bonds;
});
});
// your original view should now work
Upvotes: 3
Reputation: 1485
Try this
angular.module('app', []).factory('Topology', function ($http,$q){
return{
get: function(){
var d = $q.defer();
$http.get("data.json")
.success(function (response){
console.log(response)
d.resolve(response);
});
return d.promise;
},
}
}).controller('stageThreeCtrl', function ($scope, Topology) {
Topology.get().then(function (response) {
$scope.bonds = response.bonds;
});
});
Upvotes: 1
Reputation: 43
Try
Topology.get().then(function (data) {
$scope.bonds=data.bonds;
});
As pointed out in the comments, I didn't notice that the get function wasn't returning a promise.
To return a promise, the $http API is based on the deferred/promise APIs exposed by the $q service, so just use the code below in the get function with the factory (service).
return $http.get('data.json');
Upvotes: -1