$http POST & $http GET in 1 service - angularjs

I want create 1 service where i can POST the data and on success i can again GET the data and update the $scope.variable??
How to do that?
I've tried this way:
angular.module('mvc')
.factory('ajaxService', function($http) {
return {
getAjaxData: function(response) {
$http.get(url).success(response);
return response;
},
postAjaxdata: function(postData){
$http({
method: "post",
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
url: url,
data: data
})
.success(function(response){
ajaxService.getAjaxData(function(response) {
$scope.foo = response;
});
});
}
}
});

Capture this in postAjaxdata() to be used in the success callback to call getAjaxData().
You don't have access to the scope inside of the service (nor do you want to access it from a service). The Angular convention is to return a promise to the controller so that it can apply the response value to the scope when the promise is resolved. You can also do this using callbacks (to be consistent with the code that was posted). Here, I've added a callback to postAjaxdata()...
angular.module('mvc')
.factory('ajaxService', function($http) {
return {
getAjaxData: function(successCallback) {
$http.get(url).success(successCallback);
return successCallback;
},
postAjaxdata: function(postData, successCallback){
var that = this;
$http({
method: "post",
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
url: url,
data: data
})
.success(function(){
that.getAjaxData(successCallback);
});
}
}
});
The controller should look something like this...
function controller ($scope, ajaxService) {
// ...
ajaxService.postAjaxdata(postData, function (response) {
$scope.foo = response;
});
}

The main issue is that you can't set scope variables in the way you attempted to from the service.
You could instead use the $q service to return a promise which, when resolved, is set to your $scope.foo variable:
.factory('ajaxService', function($http, $q) {
var ajaxService = {
getAjaxData: function() {
return $http.get(url);
},
postAjaxdata: function(postData){
var deferred = $q.defer();
$http({
method: "post",
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
url: url,
data: postData
})
.success(function(){
deferred.resolve(ajaxService.getAjaxData());
});
return deferred.promise;
}
};
return ajaxService;
});
You'll also notice that I set the body of your factory to a named variable, which you can then use to call functions internally (as you did with ajaxService.getAjaxData()) before returning.
Then, in your controller, you could set your scope variable like this:
.controller('MyController', function($scope, ajaxService){
ajaxService.postAjaxdata().then(function(results){
$scope.foo = results.data;
})
})
Working Plunker
Note: my answer is not entirely dissimilar to Anthony Chu's. I noticed that he posted his just before mine, but I went ahead anyway since mine takes a slightly different approach, utilizing promises instead of callbacks.

Related

$http:badreq - GET json Object

I want to make an $http request making use of the configuration object instead of the quick method. The request is of 'GET' method and the url targets a local json file.
The code looks more or less like:
$http.get({
method: 'GET',
url: 'data.json'
}).then(function(res) {
$scope.data = res;
}, function(res) {
console.log(res);
})
The error I get is :
Error: [$http:badreq]
Here's a 'working' plunker demonstrating the problem.
The fact is that if I use the quick method $http.get('clients.json') it works.
Any help would be appreciated.
update your app.js file
var app = angular.module('app', []);
app.controller('MainCtrl', function($scope, $http) {
$http({
url: 'data.json',
type: 'GET'
}).then(function(res) {
$scope.data = JSON.stringify(res.data);
}, function(res) {
console.log(res);
})
});
DEMO
try this it works for me : plunker
app.controller('MainCtrl', function($scope, $http) {
$http({method: 'GET',url : './data.json'}).then(function(res) {
$scope.data = res;
}, function(res) {
console.log(res);
})
});
First on your index.html, you had {data}} instead of :
<body ng-controller="MainCtrl">
{{data}}
</body>
On your controller you have to invoke the $http as following (not using $http.getbut just $http) :
$http({
method: 'GET',
url: 'data.json'
}).then(function successCallback(response) {
$scope.data = response.data;
}, function errorCallback(response) {
console.log(response);
});
See working update here https://plnkr.co/edit/OCPkPYsbcHv2snef5Bj3?p=preview
Seems your code is wrong, you already use $http.get, but still add {method: 'GET'}.
I guess you want to use $http request directly.
$http({
method: 'GET',
url: 'data.json'
}).then(function(res) {
$scope.data = res;
}, function(res) {
console.log(res);
})

defer.promise returning same result in angularJS

I have a Service which fetch the data from API.When I am trying to call this service. It's returning with same value.
appName.service('FetchCustomerDate', ['$http', '$q', function($http, $q) {
var self = this;
self.getCustomerData = function(token,name) {
var deferred = $q.defer();
return $http({
method: 'GET',
url: ,
headers: {
"Authorization": token,
"x-xcmc-auth": ''
}
}).then(function(response) {
deferred.resolve(response);
return deferred.promise;
}, function(response) {
deferred.reject(response);
return deferred.promise;
});
};
}]);
I see a bit of confusion here. Let's try to clear it. If you want to use deferred object, you need to change your code a bit:
appName.service('FetchCustomerDate', ['$http', '$q', function ($http, $q) {
var self = this;
self.getCustomerData = function (token, name) {
var deferred = $q.defer();
$http({ // Do not return here, you need to return the deferred.promise
method: 'GET',
url: '...some URL here...',
headers: {
"Authorization": token,
"x-xcmc-auth": ''
}
}).then(function (response) {
deferred.resolve(response); // It's correct, you are resolving the deferred promise here.
// return deferred.promise; // You do not need to return the deferred.promise here.
}, function (response) {
deferred.reject(response); // It's correct, you are rejecting the deferred promise here.
// return deferred.promise; // You do not need to return the deferred.promise here.
});
return deferred.promise; // The function must return the deferred.promise
};
}]);
In detail, function getCustomerData must return the promise belonging to deferred object with return deferred.promise. Inside then() callback you simply resolve or reject deferred promise. You do not need to return the deferred.promise.
You can improve the code. The $http service returns a promise, and the value returned by then callbacks is wrapped by then method in a promise. Knowing that, you can remove the use of deferred object:
appName.service('FetchCustomerDate', ['$http', function ($http) {
var self = this;
self.getCustomerData = function (token, name) {
return $http({ // Here, you need to return the promise returned by $http. Than promise will contain the response returned inside "then" callbacks.
method: 'GET',
url: '...some URL here...',
headers: {
"Authorization": token,
"x-xcmc-auth": ''
}
}).then(function (response) {
return response; // Simply return the response, it will be wrapped in a resolved promise by "then()"
}, function (response) {
return response; // Simply return the response, it will be wrapped in a rejected promise by "then()"
});
};
}]);
As you can see, the 2 then callbacks simply returns the response object, for this reason you can omit them:
appName.service('FetchCustomerDate', ['$http', function ($http) {
var self = this;
self.getCustomerData = function (token, name) {
return $http({ // Here, you need to return the promise returned by $http. Than promise will contain the response form the GET call
method: 'GET',
url: '...some URL here...',
headers: {
"Authorization": token,
"x-xcmc-auth": ''
}
});
};
}]);
Usually when you fetch data with the $httpservice, you want to obtain data from the response and affect it to the $scope for instance, or process it somehow. What are you trying to do? Please clarify your question.
Normally a fetch will look something like this:
appName.service('FetchCustomerDate', ['$http', '$q', function($http, $q) {
var self = this;
function notifyError(reason) {
console.error(reason);
}
self.getCustomerData = function(token,name) {
var deferred = $q.defer();
return $http({
method: 'GET',
url: ,
headers: {
"Authorization": token,
"x-xcmc-auth": ''
}
})
.then(function onSuccess(response) {
var cfg = response.data; // process data
})
.then(function onSuccess(response) {
// chained promises
})
.then(
function onSuccess(res) {
// ... this will trigger the chain reaction
deferred.resolve(res);
},
function onFailure(reason) {
notifyError(reason); // manage the error
deferred.reject(reason);
})
;
return deferred.promise;
}
}]);

Cannot get the data in the controller from the service

app.service('customersService', function ($http) {
this.getCustomer = function (id) {
$http({
method: 'GET',
url: '/getCustomer',
params: {id: id},
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
}).success(function(data) {
console.log(data);
return data;
})
};
});
Cannot get the data in the controller from the service
The problem with this code is when i try to run this
customersService.getCustomer(customerID).then
It generates an error mentioned below:
angular.js:13294 TypeError: Cannot read property 'then' of undefined.
The main thing is the call to the service is generated and if i try to print the results on the console in the service the data is there. However i cannot get the data in my controller.
You get that error becuase you are not returning the promise from $http GET request.
Edit your code like this:
app.service('customersService', function ($http) {
this.getCustomer = function (id) {
return $http({
method: 'GET',
url: '/getCustomer',
params: {id: id},
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
});
};
});
And then with .then() in your controller, you handle the response data.
app.controller('myController', function($scope, customerService){
customersService.getCustomer(customerID)
.then(function(response){
$scope.data = response;
})
})
You simply forget to return the $http promise that is why undefined is returned. You need to do the following:
...
return $http({ ...
Try given code.
app.service('customersService', function ($http) {
var getCustomer = function (id) {
return $http({
method: 'GET',
url: '/getCustomer',
params: {id: id},
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
})
};
var customersService = {
getCustomer: getCustomer
}
return ProfileService;
});

Angular Service - Pass $http data to scope

I´m trying to create an angular function inside on Service to return acess data via $http and then return to a desired scope.
So my service it something like this;
app.service('agrService', function ($http) {
this.testinho = function(){
return "teste";
}
this.bannerSlides = function(){
var dataUrl = "data/banner-rotator.json";
// Simple GET request example :
$http({
method: 'GET',
dataType: "json",
url: dataUrl
})
.success( function(data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
//console.log(data);
return data;
}).error( function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
alert("Niente, Nada, Caput");
});
}
})
Then i want to associate the returned data to a scope inside of my main App controller... like this:
app.controller('AppCtrl', function($scope, $http, agrService) {
$scope.slides = agrService.bannerSlides();
})
Then in my template i want to loop the data like this:
<div ng-repeat="slide in slides">
<div class="box" style="background: url('{{ slide.url }}') no-repeat center;"></div>
</div>
The problem is that the data it´s only available on success and i don´t know how to pass it to my scope slides!!!!!
What i´m doing wrong?
Many thanks in advance
bannerSlides() doesn't return the values you need right away. It returns a promise that you can use to obtain the value at a later time.
In your service you can use the .then() method of the promise that $http() produces to do initial handling of the result:
return $http({
method: 'GET',
dataType: "json",
url: dataUrl
}).then(function (data) {
// inspect/modify the received data and pass it onward
return data.data;
}, function (error) {
// inspect/modify the data and throw a new error or return data
throw error;
});
and then you can do this in your controller:
app.controller('AppCtrl', function($scope, $http, agrService) {
agrService.bannerSlides().then(function (data) {
$scope.slides = data;
});
})
Use this in your service
....
this.bannerSlides = function(){
var dataUrl = "data/banner-rotator.json";
return $http({
method: 'GET',
dataType: "json",
url: dataUrl
});
};
...
And this in your controller
agrService.bannerSlides().then(function(data) {
$scope.slides = data;
}, function() {
//error
});
you don't need $q promise inside the service because the $http is returning a promise by default
The $http service is a function which takes a single argument — a configuration object — that is
used to generate an HTTP request and returns a promise with two $http specific methods: success and error
reference
here is a Fiddle Demo
You need to return a promise and update your scope in the callback:
app.service('agrService', function ($q, $http) {
this.bannerSlides = function(){
var ret = $q.defer();
var dataUrl = "data/banner-rotator.json";
// Simple GET request example :
$http({
method: 'GET',
dataType: "json",
url: dataUrl
})
.success( function(data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
ret.resolve(data);
}).error( function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
ret.reject("Niente, Nada, Caput");
});
return ret.promise;
}
})
app.controller('AppCtrl', function($scope, $http, agrService) {
$scope.slides = null;
agrService.bannerSlides().then(function(data){
$scope.slides = data;
}, function(error){
// do something else
});
})
You can't return a regular variable from an async call because by the time this success block is excuted the function already finished it's iteration.
You need to return a promise object (as a guide line, and preffered do it from a service).
Following angular's doc for $q and $http you can build yourself a template for async calls handling.
The template should be something like that:
angular.module('mymodule').factory('MyAsyncService', function($q, http) {
var service = {
getData: function() {
var params ={};
var deferObject = $q.defer();
params.nameId = 1;
$http.get('/data', params).success(function(data) {
deferObject.resolve(data)
}).error(function(error) {
deferObject.reject(error)
});
return $q.promise;
}
}
});
angular.module('mymodule').controller('MyGettingNameCtrl', ['$scope', 'MyAsyncService', function ($scope, MyAsyncService) {
$scope.getData= function() {
MyAsyncService.getData().then(function(data) {
//do something with data
}, function(error) {
//Error
})
}
}]);

AngularJS - Controller gets the data returned from Service (MVC Web API call) as undefined

I am new to AngularJS & working on a sample. In my sample app I have an MVC Web api (which returns some data from db) & it will be called from the Angular Services and returns the data to the Controller. The issue is I am getting the data in my Services success method properly but in my controller it always shows undefined & nothing is displayed in the view. Please see the code below:
My Controller code:
app.controller('CustomerController', function ($scope, customerService) {
//Perform the initialization
init();
function init() {
$scope.customers= customerService.getCustomers();
}
});
My Services code:
app.service('customerService', function ($http){
this.getCustomers = function () {
$http({
method: 'GET',
url: 'api/customer'
}).
success(function (data, status, headers, config) {
return data;
}).
error(function (data, status) {
console.log("Request Failed");
});
}
});
Please help me to fix this issue.
That's because your service defines the function getCustomers but the method itself doesn't actually return anything, it just makes an http call.
You need to provide a callback function in the form of something like
$http.get('/api/customer').success(successCallback);
and then have the callback return or set the data to your controller. To do it that way the callback would probably have to come from the controller itself, though.
or better yet, you could use a promise to handle the return when it comes back.
The promise could look something like
app.service('customerService', function ($http, $q){
this.getCustomers = function () {
var deferred = $q.defer();
$http({
method: 'GET',
url: 'api/customer'
}).
success(function (data, status, headers, config) {
deferred.resolve(data)
}).
error(function (data, status) {
deferred.reject(data);
});
return deferred;
}
});
Your problem is in your service implementation. You cannot simply return data since that is in the asynchronous success callback.
Instead you might return a promise and then handle that in your controller:
app.service('customerService', function ($http, $q){
this.getCustomers = function () {
var deferred = $q.defer();
$http({
method: 'GET',
url: 'api/customer'
})
.success(function (data, status, headers, config) {
// any required additional processing here
q.resolve(data);
})
.error(function (data, status) {
q.reject(data);
});
return deferred.promise;
}
});
Of course if you don't require the additional processing, you can also just return the result of the $http call (which is also a promise).
Then in your controller:
app.controller('CustomerController', function ($scope, customerService) {
//Perform the initialization
init();
function init() {
customerService.getCustomers()
.then(function(data) {
$scope.customers= data;
}, function(error) {
// error handling here
});
}
});
VERY late answer, but, Angular's $http methods return promises, so there's no need for wrapping everything into promise form with $q. So, you can just:
app.service('CustomerService', function ($http) {
this.getCustomers = function () {
return $http.get('/api/customer');
};
});
and then call the .success() or .error() shortcut methods in your client controller.
If you want to take it a step further and have a fully-fledged RESTful CustomerService without having to write this boilerplate, I'd recommend the restangular library, which makes all sorts of methods available to you - assuming of course your backend responds to HTTP verbs in the "standard fashion".
Then you could just do this:
app.service('CustomerService', function (Restangular) {
return Restangular.service('api/customer');
});
and call the methods Restangular makes available to you.
I use this for communication between Angular Web Data Service and Web Api Controller.
.factory('lookUpLedgerListByGLCode', function ($resource) {
return $resource(webApiBaseUrl + 'getILedgerListByGLCode', {}, {
query: { method: 'GET', isArray: true }
});
})
OR
.factory('bankList', function ($resource) {
return $resource(webApiBaseUrl + 'getBanklist_p', {}, {
post: {
method: 'POST', isArray: false,
headers: { 'Content-Type': 'application/json' }
}
});
})

Resources