I try to send some data (from a form) via $http to my backend. But I'm getting $http:baddata error when I try to send the data.
The full error is "Data must be a valid JSON object" but in my opinion, it is a valid object!
https://docs.angularjs.org/error/$http/baddata?p0=%3Cbr%20%2F%3E%0A%3Cb%3ENotice%3C%2Fb%3E:%20%20Undefined%20index:%20formData%20in%20%3Cb%3EC:%5Cxampp%5Chtdocs%5Cuno-form%5Capi%5Ccontrollers%5CFormController.php%3C%2Fb%3E%20on%20line%20%3Cb%3E26%3C%2Fb%3E%3Cbr%20%2F%3E%0A%7B%22success%22:true,%22data%22:%7B%22form%22:null%7D%7D&p1=%7B%7D
This is the code, and the console.log() result
$scope.submitForm = function(){
console.log("submitForm");
console.log($scope.formData, angular.toJson($scope.formData));
var data = {
formData: angular.toJson($scope.formData)
}
var config = {
headers : {
'Content-Type': 'application/json'
}
}
$http.post('/api/save-form', data,config)
.then(function(response){
console.log("RESPONSE", response);
},function(reason){
console.log("Err");
console.error(reason);
})
}
Console.log:
submitForm
home.controller.js:47 {firstName: "Test"} "{"firstName":"Test"}"
home.controller.js:63 Err
home.controller.js:64 Error: [$http:baddata] (...)
Model in frontend ({{formData}})
{
"firstName": "Test"
}
I have some other way's to send the data, without config, with the other $http way ($http({method: 'POST',....}) but no luck.
What I'm doing wrong here? I have created many forms and functions like this, but I never get this error...
This error can also happen when there is bad data coming from your backend, check if your response is valid.
Related
I am getting a 400 Error when sending a form data to my node.js backend. It also gives me this error: Unexpected token - in JSON at position 0 I know that it isn't a problem with my node app because I can send the same data using Postman and it works perfectly.
This is my Angular method:
const formData = new FormData();
formData.append("db", $scope.item.db.toLowerCase());
formData.append(
"collection",
$("#collection")
.find("option:selected")
.text()
.toLowerCase()
);
formData.append("owner", JSON.parse(sessionStorage.getItem("user"))._id);
formData.append("name", $scope.item.name);
formData.append("description", $scope.item.description);
formData.append("year", $scope.item.year);
formData.append("photo", $("#picture")[0].files[0]);
$http.post("items/uploadItem", formData).then(function(response) {
console.log(response.data);
});
};
If you need any more information, please leave a comment and I would be happy to provide it.
The Angular $http service is expecting standard objects, not a form object. You are sending a serialised form object to your end point. Try
const formData = {
db: $scope.item.db.toLowerCase(),
// and the rest of your object properties.
};
It turns out that I was still sending the data as a json doc. The trick was to change the http call to this:
$http.post("items/uploadItem", formData, {headers: { "Content-Type": undefined }})
i can't access token value from response of data from login api access please help me.
my code is accessing data from url and response is in json format from
my code is
authFactory.login = function( username, password ){
return $http.post('/api/login' , {
username : username,
password : password
})
.then( function (data) {
console.log(data);
AuthToken.setToken(data.token);
return data;
})
}
so "data" has below response in browser.
Object {data: Object, status: 200, config: Object, statusText: "OK", headers: function}
config:Object
data:Object
message:"successfully login!"
success:true
token:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI1OGY1ZjZlZDhlMzcyMDA4MDhkMmU4NWQiLCJpYXQiOjE0OTI1MjI1OTR9.EkTtneJvBM47LOvMUMh81XYLI_O5oByf1qjWOxliTcs"
__proto__:Object
headers:function (name)
status:200
statusText:"OK"
__proto__: Object
and if i am accessing url of login api then data is occured as
message:"successfully login!"
success:true
token:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI1OGY1ZjZlZDhlMzcyMDA4MDhkMmU4NWQiLCJpYXQiOjE0OTI1MjI1OTR9.EkTtneJvBM47LOvMUMh81XYLI_O5oByf1qjWOxliTcs"
Looks like when you are handling promise, you are calling response as data, try to rename it to response which is more human readable.
after renaming you can find data under response response.data.
authFactory.login = function( username, password ){
var queryParams = {
'username': username,
'password': password
}
$http.post('/api/login' , queryParams)
.then(function (response) {
// replaced data with response, which is more human readable
console.log(response.data);
AuthToken.setToken(response.data.token);
return response.data;
});
}
have you tried data.json().token ?
EDIT
One time happen to me that the I got confused with the response, because I named it data, and the response contained an object with the data.
In that case I had to use: data.data.token.
I hope this is also your case :)
The back end guy wants to send me a string, which will be returned by $http.post. If he sends me something like "success", I will get error like "parsing Json failed". I want him to wrap the string into object like "{"message": "success"}", which works fine. But other back end guys say that front end should comply with back end, so they will just send me the string. Is there any way that I can read the string?
This is the code I use if he sends me "{"message": "success"}", which works perfectly:
AdminService.saveCache(cache)
.then(function(data) {
var data = data.data;
if (data.message == "success") {
scope.successMessage = "Cache hours saved successfully";
} else {
scope.errorMessage = data.message;
}
}, function() {
scope.errorMessage = "Submission failed";
});
By default angular tries to detect if a http response contains JSON. Sometimes this detection fails and you get such an error as you described in your question.
You can avoid this behavior for a single request if you override the response transformation by providing an transformResponse property for on the configuration object passed to the request:
$http({
url: '...',
method: 'POST',
//Just return original response from server without parsing
transformResponse: [function (data, headers) {
return data;
}];
});
Alternatively you can change the default behavior for all your app's http requests by overriding the default response transformation:
myApp.config('$httpProvider', function($httpProvider) {
$httpProvider.defaults.transformResponse = [function (data, headers) {
return data;
}];
}]);
For more information see API Reference $http section "Transforming Requests and Responses"
the API Response Content-Type should be set to text/plain; and use POSTMAN to verify, it would save you a lot of headache
I am using ng-resource to do ajax request. I want to send extra info besides the data.
For example, I have an article entity on my server
exports.fetchArticle = function(req, res, next) {
var article = req.article
return res.json({data: article, message: 'success fetch article'})
}
The reason I wrap it is that, in the case of deletion, it makes no sense to send data, I can just return res.json({data: null, message: 'deleted successfully'})
on my client side, I have:
$scope.fetchArticle = function() {
Article.get({articleId: $routeParams.articleId}, function(response) {
$scope.article = response.data
$scope.ajaxSuccess = response.message
}, function(err) {
$scope.ajaxError = err.data.message
})
}
$scope.article is not an instance of ng-resource anymore, thus I can't do further request with $scope.article, i.e. this will cause error, since $scope.article is a plain json object:
$scope.article.$update(function(response) {...})
If I simply return res.json(article) from server, it works, but I can't send along the message.
The reason I dont generate the message from client but fetch from server is that, the error message is from server, I want to keep success message consistent with the error message.
Is there any other elegant way to send the message?
Assuming that all your servers responses follow this format:
{
data: {/*...*/},
message: 'some message'
}
You could use $http's transformResponse for that, so that you get an ngResource instance that is your returned object while still processing your message. For that, you need a transform-function:
function processMessage(data, message) {
//Do whatever you want with your message here, like displaying it
}
function transform(response) {
processMessage(response.data,response.message);
var data = response.data;
delete response.data;
delete response.message;
for(var attributeName in data) {
response[attributeName] = data[attributeName];
}
return response;
}
Then you can add this function to $http's default transfroms in the config of your app:
angular.module("yourApp",[/* ... */])
.config(function($httpProvider){
//....all your other config
$httpProvider.defaults.transformResponse.unshift(transform);
});
Now all repsonses from $http get transformed by this function, triggering processMessage and leaving you with a ngResource instance of the returned object.
I am trying to get response message from jsonp error callback in angularjs, but response data is undefined. I return the response with 409 http code. If to open jsonp url directly in browser it shows "angular.callbacks._0({"message":"Reset link is incorrect"})", but I can't get this message in error callback. What am I doing wrong?
// Extend angular app for api requests
app.factory('User', function($http) {
var User = function(data) {
angular.extend(this, data);
};
// Send link for password reset to entered email
User.reset_password = function() {
return $http.jsonp(jsonp_url + 'user/reset_pass?_method=post&user_key=' + user_key + '&callback=JSON_CALLBACK');
};
return User;
});
app.controller('ResetPasswordController', function ResetPasswordController($scope, User){
$scope.submit = function() {
var response = User.reset_password();
response.then(function(data){
//Success callback
}, function(data){
// Error callback
console.log(data) // Output: {config : {...}, data: undefined}
});
}
});
As said Brandon Tilley it is not possible to get data from jsonp response with http error code. If you want anyways to get error message you need to send something like this {result: false, msg: 'Error occured...'} with "good" http code, for example 200.