How can I convert jQuery ajax to fetch? - javascript

This was my jQuery code before. Now I want to change it to fetch.
function fetch(){
jQuery.ajax({
url: '<?php echo admin_url('admin-ajax.php'); ?>',
type: 'post',
data: { action: 'data_fetch', keyword: jQuery('#keyword').val(), pcat: jQuery('#cat').val() },
success: function(data) {
jQuery('#datafetch').html( data );
}
});
}
I have changed the code to this now but I am getting bad request 400 status code
document.querySelector('#keyword').addEventListener('keyup',()=>{
let data = {
action: 'data_fetch',
keyword: document.querySelector("#keyword").value
};
let url = "<?php echo admin_url('admin-ajax.php'); ?>";
fetch(url, {
method: 'POST', // or 'PUT'
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
.then((response) => response.text())
.then((data) => {
document.querySelector("#datafetch").innerHTML = data;
})
.catch((error) => {
console.error('Error:', error);
});
})
Am I missing something? It is from WordPress if this helps somehow.

You forgot the pcat property in the data object
jQuery, by default, sends form encoded data, not JSON encoded data. Use a URLSearchParams object instead of a string of JSON and omit the content-type header (the browser will add the correct one for you).

In your jQuery code you defined data as
data: { action: 'data_fetch', keyword: jQuery('#keyword').val(), pcat: jQuery('#cat').val() },
and in fetch you defined it as
let data = {
action: 'data_fetch',
keyword: document.querySelector("#keyword").value
};
so, you are not passing some value which was previously passed. No wonder that your server errors out. Let's change your code to
let data = {
action: 'data_fetch',
keyword: document.querySelector("#keyword").value,
pcat: document.getElementById("cat").value
};
and try this out. If it still works, then you will need to find out what differs in the request and make sure that the request you are sending via fetch is equivalent to the request you formally sent via jQuery, then it should work well, assuming that the client-side worked previously with jQuery and the server-side properly handled the requests.

Related

Using HTTP in NativeScript to send Post-data to a TYPO3-Webservice

I'm trying to send form data from a NativeScript app to a TYPO3-Webservice.
This is the JavaScript I'm using:
httpModule.request({
url: "https://my.domain.tld/webservice?action=login",
method: "POST",
headers: { "Content-Type": "application/json" },
content: JSON.stringify({
username:username,
password:password
})
}).then((response) => {
console.log("got response");
console.log(response.content);
//result = response.content.toJSON();
callback(response.content.toJSON());
}, (e) => {
console.log("error");
console.log(e);
});
But I can't read this data in the controller. Even with this:
$rest_json = file_get_contents("php://input");
$postvars = json_decode($rest_json, true);
$postvars is empty. $_POST is empty, too (which is - according to some docs - because the data is sent as JSON and thus the $_POST-Array isn't populated.
Whatever I do, whatever I try, I can't get those variables into my controller.
I tried it with fetch as well as with formData instead of JSON.stringify, same result.
I might have to add, that when I add the PHP-part in the index.php of TYPO3, $postvars is being populated. So I guess something goes missing, until the controller is called.
Any ideas?
the nativescript part seems ok, your problem must be corrected in the server side.
i use similare call and its works
// send POST request
httpModule.request({
method: "POST",
url: appSettings.getString("SERVER") + '/product/list',
content: JSON.stringify(data),
headers: {"Content-Type": "application/json"},
timeout: 5000,
}).then(response => { // handle replay
const responseAsJson = response.content.toJSON();
console.log('dispatchAsync\n\tresponse:', responseAsJson);
}, reason => {
console.error(`[ERROR] httpModule, msg: ${reason.message}`);
});

js fetch post works, but php is empty [duplicate]

This question already has answers here:
Receive JSON POST with PHP
(12 answers)
Closed 2 years ago.
I have this fetch method
loginbutton.onclick = (e)=> {
e.preventDefault();
var creds = {
login: login.value,
pass: pass.value
}
fetch('functions/asklogin.php', {
method: "POST",
header: {"Content-type": "application/json; charset=UTF-8"},
body: JSON.stringify(creds)
})
.then(resp => resp.text())
.then(data => console.log(data));
}
When I click, my xhr body is well fed:
But, if I try to echo these parameters from my asklogin.php
echo "no".$_POST['pass'].":".$_POST['login'];
All I get is no:
Thank you for your help
$_POST in PHP will recognize the only the form data (application/x-www-form-urlencoded or multipart/form-data) with a specified content type header.
For any other content type, you'll need to use php://input to read and parse the data.
For your case, changing the data you send through fetch should solve the issue.
...
fetch('functions/asklogin.php', {
method: "POST",
headers: {"Content-type": "application/x-www-form-urlencoded; charset=UTF-8"},
body: Object.entries(creds).map(([k,v])=>{return k+'='+v}).join('&') // in jQuery simply use $.param(creds) instead
})
...
An alternative solution will be changing how the PHP side reads data
...
if( is_empty($_POST) ){ $_POST = json_decode(file_get_contents('php://input'), true) }
...

JS: axios POST with large nested object and form-data

I am to post an Axios request because using get results in a 414 error.
Here's the object:
rows= {
0 : {
"name":"Thor",
"status":"active",
"email":"somuchlightning#kaboom.io",
},
1 : {
"name":"Mesa",
"status":"active",
"email":"big-mesa#tundra.com",
},
2 : {
"name":"Jesper",
"status":"stdby",
"email":"jes#slap.net,
},
}
This is just a sample of the object's format. There is 400+ elements in the real one, thus post instead of get. I am having trouble properly building the form-data on this one. Here's what I have:
let data = new FormData();
Object.keys(rows).forEach(key => data.append(key, rows[key])); // <--- this doesn't do
data.set('target', target); // <---- this comes through just fine
axios({
method: 'post',
url: 'byGrabthorsHammer.php',
data: data,
headers: {'Content-Type': 'multipart/form-data'}
}).then(function(response) {
if (response.error) {
console.log('failed to send list to target');
console.log(response);
} else {
console.log('response: ');
console.log(response);
}
});
What comes through is just [Object][Object]' when ivar_dump($_POST);`. This is not what I want. How could I rewrite this properly so I get the data to the other side (like GET...).
Yow bro, POST Are for inserting new stuff, instead of doing a post you need a patch
axios.patch it is basically the same. And it won’t fix your issue.
To fix the issue you need to set the Content-Type to application/json, then on yow
axios.post(url, data: JSON.stringify(bigObject))
.then(Rea=>Rea)
You could try stringifying the data. JSON.stringify(data)

Parse a json reply from a jquery result in php

I have a simple search form which query an external server for result with jquery
$("#formsearch").on("submit", function (event) {
// everything looks good!
event.preventDefault();
submitFormSearch();
});
function submitFormSearch(){
// Initiate Variables With Form Content
var searchinput = $("#searchinput").val();
$.ajax({
type: "GET",
url: "https://external-server/api/",
headers: {"Authorization": "xxxxxxxxxxxxxx"},
data: "action=Search&query="+searchinput,
success:function(json){
console.log(json);
$.ajax({
type: "POST",
url:'search_func.php',
data: "func=parse&json="+json,
success:function(data) {
console.log(data);
$('#risultato_ricerca').html(data);
}
});
}
});
}
The first GET ajax works properly and I get correct data but trying to send this json data to my php script in post I can't get data.
This is the code in search_func.php
if(isset($_POST['func']) && !empty($_POST['func'])){
switch($_POST['func']){
case 'parse':
parse($_POST['json']);
break;
default:
break;
}
}
function parse($json) {
$obj = json_decode($json,true);
var_dump($obj);
}
... it displays NULL
Where I'm wrong ?
EDIT:
SOLVED
changing:
data: "func=parse&json="+json,
to:
data: { func: 'parse', json: JSON.stringify(json) },
json code is correctly passed to search_func.php
Changed function parse in php file to:
function parse($json) {
$data = json_decode(stripslashes($json),true);
print_r($data);
}
Thank you.
Is the javascript json variable correctly filled (i.e. what does your console show you?) Possible you must encode the json variable to a string before posting.
i.e: instead of data: "func=parse&json="+json, use data: "func=parse&json="+JSON.stringify(json),
See this: http://api.jquery.com/jquery.ajax/
The correct syntax is: data: { func: 'parse', json: my_json_here }
If this doesn't works is probably that you have to encode the JSON to a string (see JSON.stringify())

HttpClient PostAsync equivalent in JQuery with FormURLEncodedContent instead of JSON

I wrote a JQuery script to do a user login POST (tried to do what I have done with C# in the additional information section, see below).
After firing a POST with the JQuery code from my html page, I found the following problems:
1 - I debugged into the server side code, and I know that the POST is received by the server (in ValidateClientAuthentication() function, but not in GrantResourceOwnerCredentials() function).
2 - Also, on the server side, I could not find any sign of the username and password, that should have been posted with postdata. Whereas, with the user-side C# code, when I debugged into the server-side C# code, I could see those values in the context variable. I think, this is the whole source of problems.
3 - The JQuery code calls function getFail().
? - I would like to know, what is this JQuery code doing differently than the C# user side code below, and how do I fix it, so they do the same job?
(My guess: is that JSON.stringify and FormURLEncodedContent do something different)
JQuery/Javascript code:
function logIn() {
var postdata = JSON.stringify(
{
"username": document.getElementById("username").value,
"password": document.getElementById("password").value
});
try {
jQuery.ajax({
type: "POST",
url: "http://localhost:8080/Token",
cache: false,
data: postdata,
dataType: "json",
success: getSuccess,
error: getFail
});
} catch (e) {
alert('Error in logIn');
alert(e);
}
function getSuccess(data, textStatus, jqXHR) {
alert('getSuccess in logIn');
alert(data.Response);
};
function getFail(jqXHR, textStatus, errorThrown) {
alert('getFail in logIn');
alert(jqXHR.status); // prints 0
alert(textStatus); // prints error
alert(errorThrown); // prints empty
};
};
Server-side handling POST (C#):
public override async Task ValidateClientAuthentication(
OAuthValidateClientAuthenticationContext context)
{
// after this line, GrantResourceOwnerCredentials should be called, but it is not.
await Task.FromResult(context.Validated());
}
public override async Task GrantResourceOwnerCredentials(
OAuthGrantResourceOwnerCredentialsContext context)
{
var manager = context.OwinContext.GetUserManager<ApplicationUserManager>();
var user = await manager.FindAsync(context.UserName, context.Password);
if (user == null)
{
context.SetError(
"invalid_grant", "The user name or password is incorrect.");
context.Rejected();
return;
}
// Add claims associated with this user to the ClaimsIdentity object:
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
foreach (var userClaim in user.Claims)
{
identity.AddClaim(new Claim(userClaim.ClaimType, userClaim.ClaimValue));
}
context.Validated(identity);
}
Additional information: In a C# client-side test application for my C# Owin web server, I have the following code to do the POST (works correctly):
User-side POST (C#):
//...
HttpResponseMessage response;
var pairs = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>( "grant_type", "password"),
new KeyValuePair<string, string>( "username", userName ),
new KeyValuePair<string, string> ( "password", password )
};
var content = new FormUrlEncodedContent(pairs);
using (var client = new HttpClient())
{
var tokenEndpoint = new Uri(new Uri(_hostUri), "Token"); //_hostUri = http://localhost:8080/Token
response = await client.PostAsync(tokenEndpoint, content);
}
//...
Unfortunately, dataType controls what jQuery expects the returned data to be, not what data is. To set the content type of the request data (data), you use contentType: "json" instead. (More in the documentation.)
var postdata = JSON.stringify(
{
"username": document.getElementById("username").value,
"password": document.getElementById("password").value
});
jQuery.ajax({
type: "POST",
url: "http://localhost:8080/Token",
cache: false,
data: postdata,
dataType: "json",
contentType: "json", // <=== Added
success: getSuccess,
error: getFail
});
If you weren't trying to send JSON, but instead wanted to send the usual URI-encoded form data, you wouldn't use JSON.stringify at all and would just give the object to jQuery's ajax directly; jQuery will then create the URI-encoded form.
try {
jQuery.ajax({
type: "POST",
url: "http://localhost:8080/Token",
cache: false,
data: {
"username": document.getElementById("username").value,
"password": document.getElementById("password").value
},
dataType: "json",
success: getSuccess,
error: getFail
});
// ...
To add to T.J.'s answer just a bit, another reason that sending JSON to the /token endpoint didn't work is simply that it does not support JSON.
Even if you set $.ajax's contentType option to application/json, like you would to send JSON data to MVC or Web API, /token won't accept that payload. It only supports form URLencoded pairs (e.g. username=dave&password=hunter2). $.ajax does that encoding for you automatically if you pass an object to its data option, like your postdata variable if it hadn't been JSON stringified.
Also, you must remember to include the grant_type=password parameter along with your request (as your PostAsync() code does). The /token endpoint will respond with an "invalid grant type" error otherwise, even if the username and password are actually correct.
You should use jquery's $.param to urlencode the data when sending the form data . AngularJs' $http method currently does not do this.
Like
var loginData = {
grant_type: 'password',
username: $scope.loginForm.email,
password: $scope.loginForm.password
};
$auth.submitLogin($.param(loginData))
.then(function (resp) {
alert("Login Success"); // handle success response
})
.catch(function (resp) {
alert("Login Failed"); // handle error response
});
Since angularjs 1.4 this is pretty trivial with the $httpParamSerializerJQLike:
.controller('myCtrl', function($http, $httpParamSerializerJQLike) {
$http({
method: 'POST',
url: baseUrl,
data: $httpParamSerializerJQLike({
"user":{
"email":"wahxxx#gmail.com",
"password":"123456"
}
}),
headers:
'Content-Type': 'application/x-www-form-urlencoded'
})
})

Categories