I have this in my factory
productsFactory.getOneProduct = function(){
$http({
method: 'GET',
url: '/api/products/' + $stateParams.productID
}).
success(function(data, status, headers, config){
console.log(data);
return data;
}).
error(function(data, status, headers, config){
});
}
This is my controller:
$scope.selectedProduct = ProductsFactory.getOneProduct();
console.log(data) outputs the data i want. But I get 'undefined' when I call it from controller. Guess it got something to do with returning from anonymous functions? Am I doing it wrong?
Your getOneProduct function does not return anything which means it implicitly returns undefined, hence the error.
$http returns a promise and you must return that promise from your function. So change your code to this:
productsFactory.getOneProduct = function(){
return $http({
method: 'GET',
url: '/api/products/' + $stateParams.productID
}).
success(function(data, status, headers, config){
console.log(data);
return data;
}).
error(function(data, status, headers, config){
});
}
Then in your controller:
productsFactory
.getOneProduct()
.then(response){});
You need to return the Promise that is returned from $http:
productsFactory.getOneProduct = function(){
return $http({
method: 'GET',
url: '/api/products/' + $stateParams.productID
});
}
And then in your controller:
productsFactory.getOneProduct().then(successFunction, errorFunction);
You could simplify your factory call further:
productsFactory.getOneProduct = function(){
return $http.get('/api/products/' + $stateParams.productID);
}
Related
I'm trying to write an Angular service and it seems like there is something missing. My problem is its not returning any value to my Angular controller
getPrepTimes() method is not returning the http data
But when I check the network (via Chrome dev tools) it will correctly call the external api and return a json object as a response
#my service
'use strict';
angular.module('recipeapp')
.service('prepTimeService',['$http', function($http){
this.prepTime = getPrepTimes();
function getPrepTimes(){
$http({
url: '/prep_times/index.json',
method: 'GET'
})
.success(function (data, status, header, config){
return data;
});
};
}
]);
#controller
'use strict';
angular.module('recipeapp')
.controller('recipeCtrl', ['$scope', 'prepTimeService', function($scope, prepTimeService){
$scope.prep_time = prepTimeService.prepTime;
}]);
When I checked the method getPrepTimes() with returning a string it works. What could be missing here?
A couple things are wrong with the above. You assign this.prepTime to getPrepTimes(). The () there will invoke getPrepTimes immediately, and not when you actually call it! You also need to utilize callbacks to get your data back and use it:
angular.module('recipeapp').service('prepTimeService',['$http', function($http){
this.prepTime = getPrepTimes;
function getPrepTimes(callback) {
$http({
url: '/prep_times/index.json',
method: 'GET'
}).success(function (data, status, header, config){
callback(data);
});
};
}]);
And now use it like so:
prepTimeService.prepTime(function(data) {
$scope.prep_time = data;
});
Calls to the $http service are async, which means you need to return a promise (and not a value):
this.prepTime = function() {
return $http({
url: '/prep_times/index.json',
method: 'GET'
});
};
And on the controller:
angular.module('recipeapp')
.controller('recipeCtrl', ['$scope', 'prepTimeService', function($scope, prepTimeService){
$scope.prep_time = prepTimeService.prepTime()
.success(function (data, status, header, config){
$scope.someVar = data;
});
}]);
Wrap answer with promise:
var self = this;
var deferred = $q.defer();
self.getPrepTimes = function() {
$http({
url: '/prep_times/index.json',
method: 'GET'
})
.success(function(data, status, headers, config) {
if (data.error === undefined) {
deferred.resolve(data);
} else {
if (data.error !== undefined) {
} else {
deferred.reject(data);
}
}
}).error(function(data, status, headers, config) {
deferred.reject(data);
});
return deferred.promise;
};
In controller call it:
prepTimeService.getPrepTimes().then(function(result) {
$scope.prep_time = result;
},
function(error) {
// show alert
});
This current code when ran returns TypeError: Services.updateUserData.set is not a function
Controller
Services.updateUserData.set($rootScope.user);
Services.js
this.updateUserData = function() {
return {
set: function(data) {
console.log(data);
$http({
method: 'POST',
url: 'api/data/',
data: {'data': data},
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
}).success(function(data, status, headers, config) {
console.log(data);
}).error(function(data, status, headers, config) {
console.log(data);
});
}
}
}
The code below works but I would much rather have a get and set function within updateUserData so that I am not duplicating work.
Current Code
Controller
Services.updateUserData($rootScope.user);
Services.js
this.updateUserData = function() {
console.log(data);
$http({
method: 'POST',
url: 'api/data/',
data: {'data': data},
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
}).success(function(data, status, headers, config) {
console.log(data);
}).error(function(data, status, headers, config) {
console.log(data);
});
}
updateUserData is a function and hence there is no property called set. The option is either convert it to object
this.updateUserData={set:function(){}}
or invoke it
Services.updateUserData().set($rootScope.user);
before accessing set
I am trying to access the http headers in my angular controller but I am getting undefined. Also, I am able to see the header response in my angular service which is not reflecting in my controller. Can someone please tell me what I am missing? Please see the code below:
Service:
cmApp.service('supplierService', function ($http, $q) {
this.getSuppliers = function (orderByColumn, skipRows, takeRows) {
var deferred = $q.defer();
$http({
method: 'GET',
url: 'api/supplier',
params: { orderBy: orderByColumn, skip: skipRows, take: takeRows },
timeout: 30000,
cache: false
}).
success(function (data, status, headers, config) {
// any required additional processing here
deferred.resolve(data, status, headers, config);
}).
error(function (data, status) {
deferred.reject(data, status, headers, config);
});
return deferred.promise;
}
Controller:
supplierService.getSuppliers($scope.orderby, $scope.skip, $scope.take)
.then(function (data, status, headers, config) {
**//getting undefined here.**
$scope.totalRecords = parseInt(headers('X-TotalRowCount'));
$scope.suppliers = data;
}, function (error) {
// error handling here
});
I have found the solution by myself. All I have to do is create an array and add all those values to the same & return it to the controller. Please see the updated code below:
Service:
cmApp.service('supplierService', function ($http, $q) {
this.getSuppliers = function (orderByColumn, skipRows, takeRows) {
var deferred = $q.defer();
$http({
method: 'GET',
url: 'api/supplier',
params: { orderBy: orderByColumn, skip: skipRows, take: takeRows },
timeout: 30000,
cache: false
}).
success(function (data, status, headers, config) {
// any required additional processing here
var results = [];
results.data = data;
results.headers = headers();
results.status = status;
results.config = config;
deferred.resolve(results);
}).
error(function (data, status) {
deferred.reject(data, status, headers, config);
});
return deferred.promise;
}
Controller:
supplierService.getSuppliers($scope.orderby, $scope.skip, $scope.take)
.then(function (response) {
$scope.suppliers = response.data;
$scope.totalRecords = parseInt(response.headers["x-totalrowcount"]);
}, function (error) {
// error handling here
});
This question is old, but $http() returns a promise itself. you can just return that from your service, no need to create a new promise. You can do this even after using .success() and .error(), or for that matter even after using a .then(), they keep chaining.
I had to access Token and TokenExpiry time from response headers of my Rest Service,then store it in my $rootScope.
Here is the code I used:
$scope.Authenticate=function(){
var EncDecUserPass=decodeURIComponent(encodeURIComponent($scope.LoggedUserName+':'+$scope.LoggedUserPassword)) ;
$http(
{method: 'GET',
url: 'http://localhost:53256/api/Products/Authenticate',
cache: false,
headers:{'Authorization':'Basic '+window.btoa(EncDecUserPass)}
}
).success(function(data, status, headers, config) {
//Here it goes
$rootScope.token=headers().token;
$rootScope.tokenExpirySec=headers().tokenexpiry;
}).error(function(data, status, headers, config) {
alert('Invalid User');
});
}
I have a loading icon set up on my page that looks like this:
<div class="loading-mask"
data-ng-show="action != null">
<span>{{action}} ...</span>
</div>
When I set $scope.action to a message appears in the loading box.
When loading my page I have a number of different async processes that get data. For example I have:
getUserProfiles: function ($scope) {
var url = '/api/UserProfile/GetSelect';
$http({ method: 'GET', url: url })
.success(function (data, status, headers, config) {
$scope.option.userProfiles = data;
})
.error(function (data, status, headers, config) {
alert("Error: No data returned from " + url);
});
},
and:
getSubjects: function ($scope) {
var url = '/api/Subject/GetSelect';
$http({ method: 'GET', url: url })
.success(function (data, status, headers, config) {
$scope.option.subjects = data;
})
.error(function (data, status, headers, config) {
alert("Error: No data returned from " + url);
});
},
How can I make it so that the first of these async processes causes a "Loading" message to appear and the last of the async process causes the loading box to not show any more. Note at this time I am not concerned about error messages. I just want the loading to not show when everything is completed.
To expand on what devmiles has said, but to handle the multiple asynchronous functions, you will want to set a loading flag on your first function to be called. I.e.:
getUserProfiles: function ($scope) {
$scope.loading = true;
var url = '/api/UserProfile/GetSelect';
$http({ method: 'GET', url: url })
.success(function (data, status, headers, config) {
$scope.option.userProfiles = data;
})
.error(function (data, status, headers, config) {
alert("Error: No data returned from " + url);
});
},
And then you will want to wrap each of your asynchronous functions in a promise, like so:
getUserProfiles: function ($scope) {
var deferred = $q.defer();
$scope.loading = true;
var url = '/api/UserProfile/GetSelect';
$http({ method: 'GET', url: url })
.success(function (data, status, headers, config) {
$scope.option.userProfiles = data;
deferred.resolve();
})
.error(function (data, status, headers, config) {
alert("Error: No data returned from " + url);
deferred.reject();
});
return deferred;
},
You can then call $q.all on all of your asynchronous functions, and the success callback of this will occur once all asynchronous functions have resolved:
$q.all([getUserProfiles, getSubjects]).then(function() {
$scope.loading = false;
}
This means once all of your functions have resolved, loading will be set to false.
NB: If you want to access the data of your callbacks, you can pass it in as a parameter of "deferred.resolve(x)", and then in your $q.all callback, it will be available as function(x) { do something with x }.
Hope this helps!
EDIT: Don't forget to pass in angular's promise service, $q, to the controller where your functions are.
Just set some boolean flag on when your controller is being instantiated and reset this flag in your success/error functions.
.controller('MyCtrl', function ( $scope ) {
$scope.isLoading = true;
$http({ method: 'GET', url: url })
.success(function (data, status, headers, config) {
$scope.option.subjects = data;
$scope.isLoading = false;
})
.error(function (data, status, headers, config) {
alert("Error: No data returned from " + url);
$scope.isLoading = false;
});
});
Use ng-show with this flag to show your loading thingy.
I am having trouble returning data from a factory method to a controller.
service.js
var serverFac = angular.module('serverCom', []).factory('SmsSendService', function($http){
var transform = function(data){
return $.param(data);
}
var temp = {};
temp.sendSms = function(tempJs){
$http.post("http://localhost:8080/somepath/rest/text-messages/send/batch", tempJs ,{
transformRequest: transform
}).success(function(data, status, headers, config){
//do stuff with response
});
};
temp.login = function (tempUserPassword){
$http.post("http://localhost:8080/somepath/rest/users/authenticate", tempUserPassword ,{
transformRequest: transform
}).success(function(data, status, headers, config){
//do stuff with response
}). error(function(data, status, headers, config){
console.log(status);
});
};
temp.SimList = function (){
$http.get("http://localhost:8080/RetireesClub_server/rest/sim-cards"
).success(function(data, status, headers, config){
//do stuff with response
}). error(function(data, status, headers, config){
});
};
return temp;
});
serverFac.config(function($httpProvider){
delete $httpProvider.defaults.headers.common['X-Requested-With'];
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form- urlencoded;charset=utf-8';
});
controller.js
function SimListController($scope, SmsSendService, SearchData, Search , $dialog , $location,$filter ){
smsSendService.simList().success(function(data){
$scope.sims= data;
}
}
Since you are handling the success callback in the controller, make your service function return a promise:
temp.SimList = function (){
return $http.get("http://localhost:8080/RetireesClub_server/rest/sim-cards")
};