I'm trying to load data from a service and update the view using $q, but it's not working. It works if I put the http call inside the controller, but I'd prefer it be part of the service.
Any help? Also, is there a better way to do this instead of promises?
Demo and code below.
---------- Fiddle Demo Link ----------
View
<div ng-init="getData()">
<div ng-repeat="item in list">{{item.name}}</div>
</div>
Controller
.controller('ctrl', ['$scope', 'dataservice', '$q', function ($scope, dataservice, $q) {
$scope.list = dataservice.datalist;
var loadData = function () {
dataservice.fakeHttpGetData();
};
var setDataToScope = function () {
$scope.list = dataservice.datalist;
};
$scope.getData = function () {
var defer = $q.defer();
defer.promise.then(setDataToScope());
defer.resolve(loadData());
};
}])
Service
.factory('dataservice', ['$timeout', function ($timeout) {
// view displays this list at load
this.datalist = [{'name': 'alpha'}, {'name': 'bravo'}];
this.fakeHttpGetData = function () {
$timeout(function () {
// view should display this list after 2 seconds
this.datalist = [{'name': 'charlie'}, {'name': 'delta'}, {'name': 'echo'}];
},
2000);
};
return this;
}]);
No need for ngInit or $q. This is how you should do it.
You should also not expose dataservice.list to the controller. That should be private to dataservice, which will contain most of the logic to determine whether to send the controller the existing list or update the list and then send it.
angular.module('app', [])
.controller('ctrl', ['$scope', 'dataservice', function ($scope, dataservice) {
loadData();
function loadData() {
dataservice.fakeHttpGetData().then(function (result) {
$scope.list = result;
});
}
}])
.factory('dataservice', ['$timeout', function ($timeout) {
var datalist = [
{
'name': 'alpha'
},
{
'name': 'bravo'
}
];
this.fakeHttpGetData = function () {
return $timeout(function () {
// Logic here to determine what the list should be (what combination of new data and the existing list).
datalist = [
{
'name': 'charlie'
},
{
'name': 'delta'
},
{
'name': 'echo'
}
];
return datalist;
},
2000);
};
return this;
}]);
Firstly, don't use ng-init in this way. As per the docs:
The only appropriate use of ngInit is for aliasing special properties of ngRepeat, as seen in the demo below. Besides this case, you should use controllers rather than ngInit to initialize values on a scope.
Secondly, promises are the perfect thing to use in this case, but you don't need to touch $q, as $http calls return promises for you.
To do this properly, simply return the $http result from the service:
this.getDataFromService = function() {
return $http(/* http call info */);
};
Then, inside you controller:
dataservice.getDataFromService().then(function(result){
$scope.list = result.data;
});
Also here is the updated fiddle: http://jsfiddle.net/RgwLR/
Bear in mind that $q.when() simply wraps the given value in a promise (mimicking the response from $http in your example).
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