Problems with the implementation of POST request (angularjs ($http))
I am trying to perform a POST request, but get the following error:
Error: Unexpected request: POST http://192.168.88.54:3000
No more request expected
at $httpBackend (file:///Users/vasyasemenov/workspace/tamua/ogogo-frontend/build/vendor/angular-mocks/angular-mocks.js:1176:9)
at sendReq (file:///Users/vasyasemenov/workspace/tamua/ogogo-frontend/build/vendor/angular/angular.js:7721:9)
at serverRequest (file:///Users/vasyasemenov/workspace/tamua/ogogo-frontend/build/vendor/angular/angular.js:7455:16)
at wrappedCallback (file:///Users/vasyasemenov/workspace/tamua/ogogo-frontend/build/vendor/angular/angular.js:10696:81)
at wrappedCallback (file:///Users/vasyasemenov/workspace/tamua/ogogo-frontend/build/vendor/angular/angular.js:10696:81)
at file:///Users/vasyasemenov/workspace/tamua/ogogo-frontend/build/vendor/angular/angular.js:10782:26
at Scope.$eval (file:///Users/vasyasemenov/workspace/tamua/ogogo-frontend/build/vendor/angular/angular.js:11697:28)
at Scope.$digest (file:///Users/vasyasemenov/workspace/tamua/ogogo-frontend/build/vendor/angular/angular.js:11525:31)
at Scope.$apply (file:///Users/vasyasemenov/workspace/tamua/ogogo-frontend/build/vendor/angular/angular.js:11803:24)
at HTMLButtonElement.<anonymous> (file:///Users/vasyasemenov/workspace/tamua/ogogo-frontend/build/vendor/angular/angular.js:17690:21)
My implementation of the POST request:
angular.module('App')
.config(['$httpProvider',
function($httpProvider) {
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
}
])
.service('API', function API($http, $q, PROD, PROD_HOST, DEV_HOST, API_TOKEN) {
var self = this;
self.host = (PROD ? PROD_HOST : DEV_HOST);
self.performRpcCall = {
post: function(url, params) {
var deferred = $q.defer();
var data = {
jsonrpc: '2.0',
params: params,
method: url
};
$http.post(self.host, data).success(function(data) {
if(data.result) {
deferred.resolve(data.result);
}else{
deferred.reject(data.error);
}
}).error(function(data, status, headers, config) {
deferred.reject(data);
});
return deferred.promise;
}
};
self.registerUser = function(params) {
params.token = API_TOKEN;
return self.performRpcCall.post('/api/users', params);
};
});
Where is the error? Thank you
Not sure if this is the problem or not but I've had trouble before when passing an object as the data parameter to $http.post before.
To correct that I've used jQuery's $.params(data) in the past or...
data = {
someVar : someVal,
anotherVar : anotherVal
};
return $http({
method : 'POST',
url : 'someURL/path/to/api/script',
params : data,
headers : {'Content-Type' : 'application/x-www-form-urlencoded'}
}).success(function(response){
return (angular.isDefined(response.data.result)) ? response.data.result : response.data.error;
}).error(function(response){
return { data : response.data, status : response.status };
});
data gets JSONified for the params var when passing $http a configuration object. Of course you already set the header with the provider. There is also a data config property, I haven't used that but I think it does the same but just doesn't JSONify the data into a string but rather incorporates it into the header as message data.
Related
studentService.js
app.factory('saveStudentService',['$http','$scope',function ($http,$scope) {
var studentData = {};
studentData.save = function(jsondata){
var action = "student";
var method = "POST";
$http({
url: action,
method: method,
headers: {'Content-Type': 'application/json'},
data: jsondata
}).success(function(data, status, headers, config) {
toastr.success(status +' : Data has been submitted successfully ');
}).error(function(data, status, headers, config) {
toastr.error(status + ' : Data has not been submitted successfully ');
});
};
return studentData;
}]);
I am getting this error
angular.js:13642Error: [$injector:unpr] http://errors.angularjs.org/1.5.6/$injector/unpr?p0=%24scopeProvider%20%3C-%20%24scope%20%3C-%20saveStudentService
at Error (native)
at https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js:6:412
If from studentService.js, $scope is being removed, i.e
app.factory('saveStudentService',['$http',function ($http) {
this code is working properly, and not getting any error message in console.
Following is the studentController.js file from where this studentService is being called.
StudentController.js
app.controller('saveStudentCtrl',['$scope', 'saveStudentService', function($scope,saveStudentService) {
$scope.submit_create_student = function() {
var jsondata = $scope.student;
saveStudentService.save(jsondata);
}
}]);
but if same thing i.e $scope is being added in the updateStudentService then this code is working as expected.
app.controller('updateStudentCtrl',['$scope','retriveStudentService', 'updateStudentService', function($scope,retriveStudentService, updateStudentService) {
$scope.getStudentDataFromServer = function() {
retriveStudentService.get();
};
$scope.submit_update_student = function(e) {
updateStudentService.update();
}
}]);
Could someone please clarify, what is happening here. Though able to use same thing in one place, but not able to use same process at someother place.
You cannot inject scope into services. You can inject it to controllers.
I'm new to AngularJS and
I needed to know if we can make a jQuery like Ajax call in Angular and wanted to know it's complete syntax,
if anyone could help me making the whole code syntax.
Example in jQuery I could do something like -
$.ajax(
{
url: 'someURL',
type: 'POST',
async: false,
data:
{
something: something,
somethingelse: somethingelse
},
beforeSend: function()
{
$('#someID').addClass('spinner');
},
success: function(response)
{
$('#someID').removeClass('spinner');
console.log(response);
},
complete: function(response)
{
$('#someID').removeClass('spinner');
console.log(response);
},
error: function (errorResp)
{
console.log(errorResp);
}
});
Now here's what I found out on making http call in Angular,
Need help in building the complete syntax, with all possible options -
var req = {
method: 'POST',
url: 'someURL',
headers: {
'Content-Type': undefined
},
data: {
//goes in the Payload, if I'm not wrong
something: 'something'
},
params:{
//goes as Query Params
something: 'something',
somethingElse: 'somethingElse'
}
}
$http(req)
.then(function()
{
//success function
},
function()
{
//Error function
});
now what if I want to attach a spinner on some id in the BeforeSend function like in jQuery and remove the spinner in success,
What is the Angular's way as a like to like for BeforeSend or making the http call async?
Angular even let you control this better :). Two ways can be chosen here:
1. Wrapping $http
You can write for each request with by using a wrapper of $http which will add some methods before and after you made request
app.factory('httpService',function($http){
function beginRequest() {};
function afterRequest() {};
return {
makeRequest: function(requestConfig){
beginRequest();
return $http(requestConfig).then(function(result){
afterRequest(result);
});
}
}
})
Then each time you can call this function to make a request. This is not new.
2. Using interceptor
Angular has a better way to handle for all request. It use a new concept named 'interceptor'. You write your interceptor as a normal service and push one or many interceptors into $http service and depend on type of interceptor, it will be called each time your request happen. Look at this picture to think about interceptor:
Some common task for interceptor can be: Add/remove a loading icon, add some more decorator to your http config such as token key, validate request, validate responded data, recover some request...
Here is example of a interceptor that add a token key into headers of a request
app.service('APIInterceptor', function($rootScope, UserService) {
var service = this;
service.request = function(config) {
var currentUser = UserService.getCurrentUser(),
access_token = currentUser ? currentUser.access_token : null;
if (access_token) {
config.headers.authorization = access_token;
}
return config;
};
service.responseError = function(response) {
return response;
};
})
Then add interceptor to your $http:
app.config(['$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push('APIInterceptor');
}]);
Now all request will be added a token key to header. cool right?
See here for more information:
there is eveyrthing here to help with your question :https://docs.angularjs.org/api/ng/service/$q http://chariotsolutions.com/blog/post/angularjs-corner-using-promises-q-handle-asynchronous-calls/
$http functions are async by default.
And regarding the beforesend function, you could wrap the http call in a function and add the spinner just before making the call and remove it in the success call back. Something like this,
var makeHttpRequest = function(){
$('#someID').addClass('spinner');
$http(req).then(function(){
$('#someID').removeClass('spinner');
//rest processing for success callback
},function(){
$('#someID').removeClass('spinner');
//Error callback
});
}
The way I have implemented complex get and post in my angular application is as below:
Create a CRUDService as below:
yourApp.service('CRUDService', function ($q, $http) {
this.post = function (value, uri) {
var request = $http({
method: "post",
url: uri,
data: value
});
return request;
}
this.get = function (uri) {
var request = $http({
method: "get",
url: uri
});
return request;
}
});
As you can see this service simply returns a get/post object. Somewhere in my controller I use this service as below:
$('#exampleButton').button("loading"); //set the element in loading/spinning state here
var getObj = CRUDService.get("/api/get/something");
getObj.then(function(data){
//do something
$('#exampleButton').button("reset"); //reset element here
}, function(err){
//handle error
$('#exampleButton').button("loading"); //reset element here
});
$('#exampleButton').button("loading"); //set the element in loading/spinning state here
var postObj = CRUDService.post(postData,"/api/get/something");
postObj.then(function(data){
//do something
$('#exampleButton').button("reset"); //reset element here
}, function(err){
//handle error
$('#exampleButton').button("loading"); //reset element here
});
I hope this helps :)
The http call is async - it returns a promise that you can then handle with the try() and catch() methods. You can simply wrap your calls i.e.
function makeRequest() {
$scope.showSpinner = true;
$http
.get('http://www.example.com')
.then(function (response) {
$scope.showSpinner = false;
})
.catch(function (err) {
$scope.showSpinner = false;
});
}
If you would however like you use familiar syntax akin to jQuery then you can push your own custom interceptors. This will allow you intercept the requests and response and do whatever you want. In the below example we call functions if they are defined.
angular
.module('app', [])
.config(appConfig)
.factory('HttpInterceptors', httpInterceptors)
.controller('MyController', myController);
// app config
appConfig.$inject = ['$httpProvider'];
function appConfig($httpProvider) {
// add out interceptors to the http provider
$httpProvider.interceptors.push('HttpInterceptors');
}
// http interceptor definition
function httpInterceptors() {
return {
request: function(request) {
if (angular.isFunction(request.beforeSend)) {
request.beforeSend();
}
return request;
},
response: function(response) {
if (angular.isFunction(response.config.onComplete)) {
response.config.onComplete();
}
return response;
}
}
}
// controlller
myController.$inject = ['$scope', '$http', '$timeout'];
function myController($scope, $http, $timeout) {
$scope.showSpinner = false;
$http({
method: 'GET',
url: 'https://raw.githubusercontent.com/dart-lang/test/master/LICENSE',
beforeSend: function() {
$scope.showSpinner = true;
},
onComplete: function() {
$timeout(function() {
console.log('done');
$scope.showSpinner = false;
}, 1000);
}})
.then(function(response) {
console.log('success');
})
.catch(function(err) {
console.error('fail');
});
}
.spinner {
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.min.js"></script>
<div ng-app='app' ng-controller='MyController'>
<div ng-class='{spinner: showSpinner}'>
Hello World!
</div>
</div>
I try to pass my form parameters to java rest backend but i cant.
controller
$scope.addNewThing = function () {
Myservice.addNew($scope.name);
};
service
addNew: function (name) {
var Foo = $resource($rootScope.baseUrl + '/path/addNew', {}, {
save: {method: 'POST', params: {}}
});
var results = Foo.save({name: name}, function(data) {
results = data;
});
return results;
}
//also tried this version of code
addNew: function(name) {
return $resource($rootScope.baseUrl + '/path/addNew', {}, {
save: {method: 'POST', params: {name: 'test'}}
});
}
rest backend function
#POST
#Produces("application/json")
#Path("/addNew")
public Response addNew(#FormParam("name") String name) {
try {
//when i check name here it is always null
...
}
}
I can't pass the html form parameter to java rest backend via angular. Also tried to change #FormParam to #QueryParam but it didn't work.
Did you set the default content-type on $http POST requests?
app.config(function($httpProvider) {
$httpProvider.defaults.headers.post = {};
$httpProvider.defaults.headers.post["Content-Type"] = "application/json; charset=utf-8";
});
I don'n know how to receive params value in java but I can show how to pass params from angular service. when you will want to pass params then you should use :paramsName in your URL path.
addNew: function(name) {
var addNewItem = $resource($rootScope.baseUrl + '/path/addNew/:name', {name: '#name'}, {
'post': {method: 'GET'}
});
return addNewItem.post({name: name});
}
or if you don't use /:name in your url you should pass in your header
addNew: function(name) {
var addNewItem = $resource($rootScope.baseUrl + '/path/addNew/:name', {}, {
'post': {method: 'GET', headers: { 'name': name }}
});
return addNewItem.post({name: name});
}
NB: your Content-Type should be application/json
You can try this:
CONTROLLER
$scope.addNewThing = function () {
yourService.addNew($scope.name);
};
SERVICE
angular.module('MyApp')
.service('yourService',['$http', function ($http) {
this.addNew = function (data) {
$http({
url: 'YourURL',
method: 'POST',
data: data, // your $scope.name
headers: {'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8'}
})
.success(function (response) {
console.log('good');
})
.error(function (response) {
console.log('error');
});
};
}]);
JAVA REST API
#POST
#Path("/addNew")
#Consumes("*/*")
public Response addNew(String name) {
// use here your String name
}
Using jQuery params solved my problem
Here is the correct way:
Myservice.addNew().save($.param({
name:$scope.name
}),function(data){
console.log(data);
},function(err){
console.log(err);
});
I can pass the parameters like this with $resource service.
I'm trying to set data to controller using my service viewShare, when i look to my console i can see the console.log of controller coming first and undefined but the services started first the strange is after this console.log, i can see the console.log from viewShare populated. If i try the function in controller again then my controller is populated correctly.
my controller:
$scope.getLine = function(search){
arcTouchAPI.getLine(search);
console.log(viewShare.getDetails);
$scope.details = viewShare.getDetails.details; //angular ignores my viewShare call and go to console.log($scope.details) than it start the viewShare service
$scope.$apply;
console.log($scope.details);
};
my service API:
var _getLine = function(search){
var encoded = $base64.encode("xxxx:xxxx");
$http({
url: "https://api.appglu.com/v1/queries/findRoutesByStopName/run",
headers : {
"X-AppGlu-Environment":"xxxx",
"Authorization": "Basic "+encoded,
"Content-Type" : "application/json; charset=utf-8"
},
method: 'POST',
data: {
"params":{
"stopName": "%"+search+"%"
}
}
}).then(function(response){
viewShare.add(response.data.rows);
// console.log($rootScope.details + "details");
console.log(response.data.rows);
});
}
return {
getLine : _getLine
}
});
my service to share data between views:
angular.module('myApp').factory('viewShare', function viewShare() {
var messages={};
var _add = function(message){
messages.details = "";
messages.details=message;
console.log(messages.details);
return messages.details;
};
var _getDetails = function(){
return messages;
};
return{
getDetails: messages,
add: _add
}
});
$http call is non-blocking, which means that your console.log is executed straight after your request is sent to getLine (as coded), however this does not wait for the $http call to finish, and therefore has no data right away. You should return the $http promise from _getLine, and wait for the promise to resolve, before trying to getDetails. Furthermore, an explicit call to $scope.$apply is not necessary.
var _getLine = function(search){
var encoded = $base64.encode("xxxx:xxxx");
return $http({ // add return statement here to return a promise
url: "https://api.appglu.com/v1/queries/findRoutesByStopName/run",
headers : {
"X-AppGlu-Environment":"xxxx",
"Authorization": "Basic "+encoded,
"Content-Type" : "application/json; charset=utf-8"
},
method: 'POST',
data: {
"params":{
"stopName": "%"+search+"%"
}
}
}).then(function(response){
viewShare.add(response.data.rows);
// console.log($rootScope.details + "details");
console.log(response.data.rows);
});
}
Change controller to:
$scope.getLine = function(search){
arcTouchAPI.getLine(search).then(function(){
console.log(viewShare.getDetails);
$scope.details = viewShare.getDetails.details;
});
};
I have this request:
$http({
method: 'get',
url: '/api/items/',
params: {a: 1, b: 2, c: 3}
}).success(function (response) {
console.log(response);
}).error(function (err) {
console.log(err);
});
Is there a way, to fetch the url it used to make the request after the request has been made(in the callback or otherwise)?
I would want the output:
http://www.example.org/api/items?a=1&b=2&c=3
Here the same thing is done with jquery.
The success handler gets 4 parameters passed into it:
$http
.get({ url: '/someUrl', params: { q: 3 } })
.success(function(data, status, headers, config) {});
The fourth parameter config has the following properties:
{
method: "GET",
url: {
url: '/someUrl',
params: {
q: 3
}
}
}
You can use window.location.origin to get the base url and build a simple function to concat it all together.
This function should yield the expected response:
var baseUrl = window.location.origin;
var query = [];
Object.keys(config.url.params || {}).forEach(function (key) {
var val = config.url.params[key];
query.push([key, val].join('=')); // maybe url encode
});
var queryStr = query.join('&');
var fullPath = baseUrl + config.url.url + '?' + queryStr;
Unfortunately, this function will only work as long as the parameters are passed in the format described above. If you pass them in a different format, you'll have to modify this function a bit. You can use this as a playground.
Afaik, there is no simpler way. At least a feature request exists.
See the docs of $http for reference
This config parameter of the callback has the url as a property:
// Simple GET request example :
$http.get('/someUrl').
success(function(data, status, headers, config) {
console.log(config.url);
}).
error(function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
Based on: https://docs.angularjs.org/api/ng/service/$http
You can use http request Interceptor.
Configure the Interceptor in config function using $httpProvider
Whrein for request Interceptor you can able to see the URL and params that you passed with URL prior to making the request
try just looking at the XHR Request urls in your browser dev tools