Angular POST request to api sending [object, Object] - javascript

I am trying to make a functionality to my app that takes the products from an order and sends them to cart.. so basicaly it repeats the whole order.
I get the order successfully but am having trouble sending it back to the API with POST method.
My API call in cart.service.ts file is:
repeatOrder(products: SingleOrder['izdelki']) {
return from(Preferences.get({key: 'TOKEN_KEY'})).pipe(
switchMap(token => {
const headers = new HttpHeaders().set('Authorization', `Bearer ${token.value}`);
const formData: any = new FormData();
formData.append('products', products);
return this.httpClient.post(`${environment.apiUrl}cart/repeatorder`, formData, {headers, observe: 'response'});
}),
catchError(err => {
console.log(err.status);
if (err.status === 400) {
console.log('Error 400: ', err.error.message);
}
if (err.status === 401) {
this.authService.logout();
this.router.navigateByUrl('/login', {replaceUrl: true});
}
return EMPTY;
}),
);
};
and this is the repeat purchase function in order-view.page.ts file:
repeatThisPurchase() {
this.repeatOrderArr= [...this.orderProducts];
this.cartService.repeatOrder(this.repeatOrderArr).subscribe(
data => {
console.log('Data sent to cart: ', data);
},
error => {
console.log('Error', error);
}
);
}
and this is the button I use to trigger this repeatPurchase function:
<div class="btn-wrapper">
<ion-button color="vigros" class="purchase-btn" size="default" type="submit" (click)="repeatThisPurchase()" expand="block">Ponovi nakup</ion-button>
</div>
I am getting error 500 in my console in browser and the payload in Networks tab is:
products: [object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
What am I doing wrong?

try not using formdata (formdata is mostly used to send files)
const headers = new HttpHeaders().set('Authorization', `Bearer ${token.value}`);
return this.httpClient.post(`${environment.apiUrl}cart/repeatorder`,{ products }, { headers });
Do you know what your api is expecting as request body?

Consult the documentation for append:
value
The field's value. This can be a string or Blob (including subclasses such as File). If none of these are specified the value is converted to a string.
You have:
const formData: any = new FormData();
formData.append('products', products);
Based on the output, products is an array of objects (since a comma seperated list of [object Object] is what you get when you convert such a thing to a string).
You need to encode the data somehow. The specifics will depend on how your server side code is trying to process it but one possible approach would be to encode each object as JSON and append them one by one, using a [] on the end of the name to mark it as an array for PHP and some Node.js libraries:
products.forEach(product => {
formData.append('products[]', JSON.stringify(product));
});
Again, I must emphasise that the specifics depend on your server-side code. It might be better to simply encode products as JSON and send an application/json formatted request instead of using FormData to send a multipart/form-data request.

Related

Can't pass array from react to django

I m trying to get an array from react frontend (stored in local storage) to my view class in django but i'm getting this error:
In console:
GET http://127.0.0.1:8000/api/quiz/multiple/ 500 (Internal Server Error)
Django LOGS:
for quiz in quizzes:
TypeError: 'NoneType' object is not iterable
ERROR:django.server:"GET /api/quiz/multiple/ HTTP/1.1" 500 20064
Here's how i store the data in the LocalStorage:
localStorage.setItem('quizzes', JSON.stringify(quizList));
history.push('/start')
And here's how i get it from local storage and pass it to the django using axios:
export default function QuizPage() {
const [DataState,setDataState] = useState([]);
const storedQuizzes = JSON.parse(localStorage.getItem("quizzes"))
useEffect(() => {
axiosInstance
.get(`quiz/multiple/`, {
quizzes: storedQuizzes
}).then((res) => {
setDataState(res.data);
})
.catch((function (error) {
console.log(error)
}));
}, [setDataState]);
and, finally, that's my django view:
class MultipleQuizView(APIView):
permission_classes = [IsAuthenticated]
def get(self,request):
questionsList = []
quizzes = request.data.get('quizzes')
for quiz in quizzes:
currentQuiz = Quiz.objects.get(url=quiz)
quizSerializer = QuizSerializerForMultipleQuizzes(currentQuiz)
question = Question.objects.filter(quiz__url=quiz)
questionSerializer = QuestionSerializer(question, many=True)
quizSerializerData = quizSerializer.data.copy()
quizSerializerData["questions"]=questionSerializer.data
questionsList.append(quizSerializerData)
if questionsList:
return Response(questionsList)
else:
return Response(status=status.HTTP_400_BAD_REQUEST)
I'm pretty sure the problem isn't from my view class because i tested it using Postman and it works without any problem.
EDIT:
I just tryed with postman using this body and it works properly:
https://i.stack.imgur.com/3RJ5A.png
So i need to send data from react like this but i don't know how:
{
"quizzes":["securitate","aparare"]
}
Try changing the second param to axios.get as follows:
axiosInstance
.get(`quiz/multiple/`, {
params: {
quizzes: storedQuizzes
}
}).then(...)
Read more about the properties that the second param supports.
SOLVED!
The problem was that i wrote:
quizzes = request.data('quizzes')
instead of:
quizzes = request.data['quizzes']

How to add array of objects to apollo client mutation request?

I am building a nativescript mobile application which consume graphql API, and I am using apollo client via apollo boost.
The problem appear when I am trying to send array of objects inside the mutation like below:
let {
to,
total,
drugList
} = order
apolloClient.mutate({
mutation: gql `mutation {
makeOrder(
to: "${to}",
total: ${total},
drugList: ${drugList}
){
id
}
}`
}).then((res) => {
console.log(res)
}).catch((error) => {
console.log(error)
})
I have tried to log the drugList inside a template literals like:
console.log(`${drugList}`)
But I got [object object],[object object] then I have tried to use ${[...drugList]} instead and I got the desired structure of array of objects but the mutate function of apollo client doesn't accept it (doesn't execute the mutation or log an error).
Am I miss something to make it run or are there any recommendation to run it?
Thanks to Bergi, after his notice that gql-tagged template literal cannot be compared to the simple template string in a console.log test.
So I have searched around this and figured out that variables property would solve this problem.
Here is the final result:
let {
to,
total,
drugList
} = order
apolloClient.mutate({
mutation: gql `mutation ($to: ID!, $total: Float!, $drugList: [OrderDrugsListInput!]!) {
makeOrder(
to: $to,
total: $total,
drugList: $drugList
){
id
}
}`,
variables: {
to: to,
total: total,
drugList: drugList
}
}).then((res) => {
console.log(res)
}).catch((error) => {
console.log(error)
})

Axios - How to read JSON response?

Axios 0.17.1
.then(function (response) {
console.log(response);
//console.log(response.status);
//It is an error -> SyntaxError: Unexpected token u in JSON at position 0
console.log(JSON.parse(response.data.error));
console.log(response.data.error); //undefined.
The console.log of response is
{data: "{"error":"Name must be entered with more than one … NULL↵
["isPipe":protected]=>↵ NULL↵ }↵}↵", status: 203, statusText:
"Non-Authoritative Information", headers: {…}, config: {…}, …} config
: {adapter: ƒ, transformRequest: {…}, transformResponse: {…}, timeout:
0, xsrfCookieName: "XSRF-TOKEN", …} data : "{"error":"Name must be
entered with more than one character."}object(Slim\Http\Response)#32
(5) {↵ ["status":protected]=>↵ int(200)↵
["reasonPhrase":protected]=>↵ string(0) ""↵
["protocolVersion":protected]=>↵ string(3) "1.1"↵
["headers":protected]=>↵ object(Slim\Http\Headers)#33 (1) {↵
["data":protected]=>↵ array(1) {↵ ["content-type"]=>↵
array(2) {↵ ["value"]=>↵ array(1) {↵ [0]=>↵
string(24) "text/html; charset=UTF-8"↵ }↵
["originalKey"]=>↵ string(12) "Content-Type"↵ }↵ }↵ }↵
["body":protected]=>↵ object(Slim\Http\Body)#31 (7) {↵
["stream":protected]=>↵ resource(59) of type (stream)↵
["meta":protected]=>↵ NULL↵ ["readable":protected]=>↵ NULL↵
["writable":protected]=>↵ NULL↵ ["seekable":protected]=>↵
NULL↵ ["size":protected]=>↵ NULL↵ ["isPipe":protected]=>↵
NULL↵ }↵}↵" headers : {content-type:
"application/json;charset=utf-8"} request : XMLHttpRequest
{onreadystatechange: ƒ, readyState: 4, timeout: 0, withCredentials:
false, upload: XMLHttpRequestUpload, …} status : 203 statusText :
"Non-Authoritative Information"
proto : Object
JSON.parse(response.data) as well as response.data.error -> Both are giving error. How can i read the data?
Slimframework 3.
$data = array('error' => 'Name must be entered with more than one character.');
$newResponse = $response->withJson($data, 203);
return $newResponse;
In Axios responses are already served as javascript object, no need to parse, simply get response and access data.
Assuming the response from the server looks like this:
{"token": "1234567890"}
Then in Axios you can access it like this:
console.log( response.data.token )
As already written, Axios already returns JSON by default. Just use response.data as simple JS object.
However, following insight might help others: I had an issue that Axios returned the response as a string. When investigated I discovered that the server returned an invalid JSON (it was a static file server). When fixed the JSON format, Axios used JSON instead of string again.
you can simply get it as following,
ex:
{
"terms": {
"title": "usage",
"message": "this is the usage message"
}
}
when the response look like this,you can get it using "response.data",and so on....
.then(response =>
console.log( response.data.terms.message)
Cheers !
I had a similar format response as the one in console log and my issue was that my .json file wasn't properly formatted. I was missing a comma. Post your json file to have a look.
axios by defualt convert response to JSON, you must use response.data instead of response
export const addPosts = () => async (dispatch) => {
await axios('https://jsonplaceholder.typicode.com/todos/1')
.then(response => dispatch({type: postActionTypes.POSTS, payload: response.data}))}
For some reason, in my case the JSON was properly formatted but was returned as string anyway. With this workaround I solved the issue.
// ...
return await this.axios_instance.request<T>({
method,
url,
headers,
params,
transformResponse: (data) => JSON.parse(data), // <----------
data,
});
Simply put, I explicitly told to transform the response using JSON.parse. For some reason this worked, while other answers didn't.
This worked for me!! Hope it helps.
Here is sample code,
try {
const res = await axios.get("/end-point");
console.log("JSON data from API ==>", res.data);
} catch (error) {
// handle error
}
I had a similar problem. As others have pointed out, axios reads the json as a js object and you can easily move through the hierarchy to get your field data.
However, for me axios did not want to read the json as an object and instead returned a string. The cause was that there was a hanging comma at the end of the json due to a previous row deletion in the file. So the file content wasn't valid json, and axios simply returned a string.
Remove the comma, everything worked.
I would suggest to check the json for any incorrect syntax.
I had the same problem and I found that I was not reading data properly. Finally, I got a solution. try this.
my data was like:
response = [{"myname","Anup","age":23,"Education":"Graduation"}]
I was trying to retrieve data like(this was giving output undefined)
axios('https://apiurl.com')
.then((reponse)=>{
const recieved_Data=fetchdata.data;
console.log(recieved_Data.name);
})
Correct Approach:
axios('https://apiurl.com')
.then((reponse)=>{
const recieved_Data=fetchdata.data;
console.log(recieved_Data[0].name);
})
as you can see i have passed the index value of the array of my response recieved_Data[0].name And this gave me the correct output.
Vote me if this works for you.
Thanks!
So I came across this post in search of an answer to my question. "How to access data in a json file returned by an api." Nonetheless, what worked for me at the end of the day was an answer to a similar question on stackoverflow to which the link is Axios. How to get error response even when api return 404 error, in try catch finally.
However, here is the code I used to access my error codes returned by my backend api.
axios.get(/sanctum/csrf-cookie).then(response => {
axios.post(api/register, registerInfo)
.then(response => {
console.log('This is the response: ' + response.data.errors);
}).catch(error => {
console.log('This is the error: ' +
error.response.data.errors.name);
});
});

Node js http server accept POST and accept JSON

I am trying to create one Node js server with http package. I want to receive only POST request which I have already implemented it. The problem which I am facing is that I am not able to parse JSON correctly (I am expecting one JSON to be attached).
I tried using JSON.parse but that doesn't parse whole json content. It leaves some values as [Object] which is wrong. I saw few packages which is JSONStream but I am not sure how to implement in this case.
server.on('request', function(req, res){
if(req.method == 'POST')
{
var jsonString;
req.on('data', function (data) {
jsonString = JSON.parse(data);
});
req.on('end', function () {
serverNext(req, res, jsonString);
});
}
else
{
res.writeHead(405, {'Content-type':'application/json'});
res.write(JSON.stringify({error: "Method not allowed"}, 0, 4));
}
res.end();
});
Request example:
Here d = JSON file content. (I did this in Python to make this example request)
r = requests.post('http://localhost:9001', headers = {'content-type': 'application/json'}, data = json.dumps(d))
Note: I am able to parse JSON correctly but there are some cases when it shows something like this:
{ 'Heading':
{ 'Content':
{ sometext: 'value',
List: [Object], // Wrong
test: [Array] } } } // Wrong
Update:
Inside serverNext() I am getting few values like:
var testReq = Object.keys(jsonData)[0];
var testId = Object.keys(jsonData[testRequest])[0];
var test = jsonData[testRequest][testId]
Further if I keep on extracting values then at some point it encounters [Objects] value and get crashed.
I can reproduce this "problem" with data as { "Foo": {"Bar": {"Some data": [43, 32, 44]} } } -- it returns the following result: { Foo: { Bar: { 'Some data': [Object] } } }.
As OP mentioned in question, the JSON is parsed correctly, the reason why [Object] is displayed in result is: when JavaScript Object is returned to display, it would be converted to String first by toString() automatically, which will make all object (including array) as [Object] in text.
To display the real content, JSON.stringify() need to be invoked. In your case, the code would be:
req.on('end', function () {
serverNext(req, res, JSON.stringify(jsonString));
});
Please note it is better to rename variable jsonString as jsonObject.

JS Fetch api and Symfony2 FOSRestBundle

Currently I am trying to get a response from my Symfony2 FOSRest Controller using Javascript Fetch API. In my controller I am serving a response with the following code:
return View::create()
->setStatusCode(200)
->setData(array('success'=>true));
And in my JS I am getting it with this:
fetch(url, 'get').then(
function (response) {
if (response.status !== 200) {
console.log('Problem, status: ' + response.status);
return;
}
response.json().then(function (data) {
console.log('OK');
if (typeof callback == 'function')
return callback(data);
});
}
).catch(function (err) {
Console.log(err);
});
As a result my controller is giving me a pure json which I can see (in Chrome Dev Tools under Response section) if I type my url directly into browser, but when js code is executed I see the following error:
Uncaught (in promise) SyntaxError: Unexpected token <
which is related to my initial file which begins from !doctype html. In my debugger if I log response.body I see that it is ReadableByteStream, but not my json. I think that the problem is somewhere in Symfony because I can read my json if I send it from regular .php file but not from RESTFul controller. Any help would be appreciated.
UPD:
when I changed response.json() to response.text() I finally got the data)) Is there any reason for that? And in addition in my url I have query string parameters (like ?par1=1&par2=2) which I want to pass to my REST Controller and which I get when I again type my url into browser directly with the following method:
$data = $request->query->get('data');
But when I pass it with JS fetch (in url parameter) no data is transferred to controller. Any idea what to do in this case? Thank You
UPD2
My symfony config.yml
fos_rest:
param_fetcher_listener: true
body_listener: true
format_listener: true
view:
formats:
json: true
xml: false
html: false
rss: false
templating_formats:
json: false
xml: false
html: false
rss: false
view_response_listener: 'force'
sensio_framework_extra:
view: { annotations: false }
router: { annotations: true }
Try to add this in your config :
fos_rest:
# ...
view:
# ...
formats:
json: true
If it doesn't work, add the following :
fos_rest:
# ...
format_listener:
rules:
- { path: '^/yourApiPrefix', priorities: ['json'], fallback_format: json, prefer_extension: false }

Categories