Reputation:
I'm just starting out in angular, and i'm building a simple item management app that loads items from a json file, and shows the items in a list view. I'll be allowing the user to edit and create new data as well, but i can't seem to get past the first step.
When I load the data directly in my list controller, It works just fine. While reading up on best practices, it seems like you shouldn't communicate directly with a json file in your controller, but rather handle these things within a factory (let me know if i'm mistaken). I can't get it to work though. Here's my code:
var app = angular.module('itemsApp', ['ngRoute']);
app.config(function($routeProvider) {
$routeProvider
.when('/', {
controller:'ListCtrl',
templateUrl:'list.html'
})
.when('/edit/:itemId', {
controller:'EditCtrl',
templateUrl:'detail.html'
})
.when('/new', {
controller:'CreateCtrl',
templateUrl:'detail.html'
})
.otherwise({
redirectTo:'/'
});
})
app.factory('ItemsFactory',function($http){
return {
getItems: function() {
return $http.get('js/items.json')
.then(function(res){
return res.data;
});
}
};
});
app.controller('ListCtrl', function($scope, $http, ItemsFactory) {
$http.get('js/items.json')
.then(function(res){
$scope.items = res.data;
});
});
The controller works fine as i have it here, however, when i try to just set $scope.items to the result of ItemsFactory.getItems();, I get nothing. Any ideas why?
Upvotes: 0
Views: 219
Reputation: 5333
Returning inside the then
promise method doesn't return any to the caller of getItems
(like in any other callback). I suggest you to manage that kind of situation in this way:
app.factory('ItemsFactory',function($http){
return {
getItems: function() {
return $http.get('js/items.json');
}
};
});
app.controller('ListCtrl', function($scope, ItemsFactory) {
ItemsFactory.getItems().then(function(res){
$scope.items = res.data;
});
});
Hope it helps. Dario
Upvotes: 1
Reputation: 4590
The best practices you are reading are absolutely right and you should have all the server communications inside one seperate module which will just have all the factories doing server exchange there.
Then you can just inject this, let's say integration module and all the factories required for server communctions become available.
Now, a sample factory can be like:
angular.module('integrationModule')
.factory('ItemsFactory',function($http){
return {
getItems: function() {
return $http.get('js/items.json');
}
};
});
app.controller('ListCtrl', function($scope, ItemsFactory) {
ItemsFactory.getItems().then(function(res){
$scope.items = res.data;
});
});
//credits Dario
or this is my preferred way(no promises needed here)
angular.module('integrationModule')
.factory('getLocaleProperties', ['$http', function($http) {
return function(requestObj, callBackFunc){
console.log('@getLocaleProperties:');
console.log(requestObj);
$http.get('assets/locale/localeProperties.json')
.success(function(data) {
callBackFunc(data);
})
.error(function(){
console.log('error in get Locale properties');
});
}
}])
Now if you notice, I am passing a callback function which is executed only when the $http call is successful, so in controllers you can inject this factory and pass it some function like:
getLocaleProperties({//some request object when posting/as query params in url}, function(data){
//do some operation on the data
})
This way I can call the factory from different controllers and perform different actions when the call is successful. Just I need to pass different callback functions.
You can also use promise, like the way you are doing, but they are only needed when you want a synchronous call like behaviour, rest can be done be callbacks.($http call is specified async in angular source code).
Hope this helps.
Upvotes: 0