Sending json via ajax in wordpress using Vanilla JS - javascript

I am sending a json in my server using vanilla JS and it returns a bad request, it seems the server only wants a key value pair like 'page=pageData&action=act', when i do this it works, but i would want to send data that way. Is there a way to make it possible?
When i try to make it in jquery it works fine.
$('.more-headlines').on('click', function() {
var pageData = $(this).data('page');
var pageURL = $(this).data('url');
var act = 'load_more';
var jsondata = {
page : pageData,
action : act
}
var xhr = new XMLHttpRequest();
xhr.open('POST', pageURL, true);
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.onload = function() {
if (xhr.status >=200 && xhr.status < 400) {
var data = JSON.parse(xhr.responseText);
console.log(data);
} else {
console.log('sad');
}
};
xhr.send(JSON.stringify(jsondata));
});
This is my code in jquery
$('.more-headlines').on('click', function () {
var that = $(this);
pageData = $(this).data('page');
newPage = pageData+1;
pageURL = $(this).data('url');
act = 'load_more';
that.addClass('icon-spin');
that.find('span').html('loading headline');
jsondata = {
page : pageData,
action : act
}
$.ajax ({
type: 'POST',
url: pageURL,
data: jsondata,
success: function(response) {
setTimeout( function () {
that.data('page', newPage);
$('#featureOnDemand ul').append(response);
that.removeClass('icon-spin');
that.find('span').html('See more headlines');
}, 500);
}
});
});
I looked at the network tab in chrome and i saw that the send request becomes a key value pair like 'page=pageData&action=act'.
I am stuck in this part because i want to make a vanilla js ajax request in my project. Any idea would be much appreaciated. Many thanks!

You want to serialize your object data. Here's a helper function you can pass your object into:
var serializeObject = function (obj) {
var serialized = [];
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
serialized.push(encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]));
}
}
return serialized.join('&');
};

Related

Vue error: In strict mode code, functions can only be declared at top level or inside a block

I'm running a Vue script with a text box and submit button, I'm calling an api to POST what I write in the textbox to the api and to return information back from the API, I'm getting this error mentioned in the title eventhough I've written the Javascript functions in vue as it should be?
With the script I'm first setting up a new XMLHttpRequest, initiating the header and api key for both GET and POST methods. I've then created 2 functions to get the data from the textbox and send them to the API, then making another button with the other function to send back the data.
I went through this approach because I kept getting a CORS issue and the API needed me to declare an access control origin header, is there anything I've done wrong with this code? Any help would be greatly appreciated
<script>
export default {
name: 'ProperForm'
}
methods: {
StartClient: function () {
this.get = function(Url, Callback){
var aHttpRequest = new XMLHttpRequest();
aHttpRequest.onreadystatechange = function() {
if (aHttpRequest.readyState == 4 && aHttpRequest.status == 200)
Callback(aHttpRequest.responseText);
}
aHttpRequest.open("GET", Url, true);
aHttpRequest.setRequestHeader("X-Api-Key", "eVnbxBPfn01kuoJIdfgi46TiYNv8AIip1r3WbjsX");
aHttpRequest.send(null);
}
this.post = function(Url, message, Callback) {
var aHttpRequest = new XMLHttpRequest();
aHttpRequest.onreadystatechange = function() {
if (aHttpRequest.readyState == 4 && aHttpRequest.status == 200)
Callback(aHttpRequest.responseText);
}
aHttpRequest.open("POST", Url, true);
aHttpRequest.setRequestHeader("x-api-key", "eVnbxBPfn01kuoJIdfgi46TiYNv8AIip1r3WbjsX");
aHttpRequest.send(message);
}
}
var client = new StartClient();
submitData: function () {
document.getElementById('inputBox').disabled = true;
var targetInputButton = document.getElementById("inputBox").value;
var message = '{"targetInputButton":"' + targetInputButton + '"}';
client.post('https://le75bkfcmg.execute-api.eu-west-2.amazonaws.com/dev/start-trace', message, function(response) {
document.getElementById('jobId').innerHTML = response;
});
}
sendBackData: function () {
var jobId = document.getElementById("jobId").innerHTML;
var message = '{"jobId":"' + jobId + '"}';
client.post('https://le75bkfcmg.execute-api.eu-west-2.amazonaws.com/dev/check-trace', message, function(response) {
document.getElementById('report').innerHTML = response;
});
}
}
</script>
New way I wrote var client:
StartClient: function () {
var client
},
You need put your methods object inside export and split the methods to comma
<script>
export default {
name: 'name',
methods:{
foo(){
},
bar(){
}
}
}
UPD: var client = new StartClient();
defined outside the method

Native JS Ajax posted Object to ASP.Net is null

I've got working code in JQuery Ajax, however I've been told I have to use Native JS code to use it, and I'm not very familiar with using native JS for ajax, and most of the internet examples are basic ones. Basically, I have this object:
var Narudzba =
{
SifraNarudzbe: "AAA",
DatumNarudzbe: "",
Osigurano: document.getElementById("checkOsiguranje").value,
BrzaDostava: document.getElementById("checkBrza").value,
KlijentId: document.getElementById("klijentid").value,
Adresa: AdresaVar,
StatusNarudzbeID: 2,
Primaoc: PrimaocVar,
VrijemeIsporuke: null,
CijenaNarudzbe: UkupnaCijena,
NacinPlacanja: parseInt(document.getElementById("NacinPlacanja_Select").value)
};
Which I'm trying to post to my Controller. Here's how my working code in Jquery Ajax looks:
$.ajax({
url: "/klijentarea/klijent/SnimiNarudzbu",
data: Narudzba,
type: 'POST',
success: function (data) {
for (var i = 0; i < stavke_niz.length; i++) {
stavke_niz[i].NarudzbeId = parseInt(data);
}
stavke_niz = JSON.stringify(stavke_niz);
$.ajax({
url: "/klijentarea/klijent/SnimiStavke",
type: "POST",
dataType: "json",
data: stavke_niz,
contentType: 'application/json',
success: function (data) {
if (data === true) {
var id = document.getElementById("klijentid").value;
window.location.href = '/KlijentArea/Klijent?id=' + id;
}
}
});
}
});
Basically, it creates an order (Narudzba) with all sorts of details, posts it to this controller:
[HttpPost]
public int SnimiNarudzbu(Narudzbe Narudzba)
{
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
var stringChars = new char[8];
var random = new Random();
for (int i = 0; i < stringChars.Length; i++)
{
stringChars[i] = chars[random.Next(chars.Length)];
}
var finalString = new String(stringChars);
Narudzba.SifraNarudzbe = finalString;
Narudzba.DatumNarudzbe = DateTime.Now;
ctx.Primaoci.Add(Narudzba.Primaoc);
ctx.Naruzbee.Add(Narudzba);
ctx.SaveChanges();
int newid = Narudzba.Id;
return newid;
}
Then I use the returned new ID, and assign it to all the objects inside stavke_niz, which is an array of order listings which gets created elsewhere in the code, and require OrderID before being added to database (I can add that code as well if necessary). Then the array with the updated OrderIDs gets sent to this controller:
[HttpPost]
public string SnimiStavke(IEnumerable<StavkaNarudzbe> stavke_niz)
{
if (stavke_niz != null)
{
ctx.StavkeNarudzbi.AddRange(stavke_niz);
ctx.SaveChanges();
return "true";
}
return "false";
}
Which successfully accepts the JSON posted with AJAX and adds the stuff to the database. Now, when I try to post in Native, like so:
var xhr = new XMLHttpRequest();
xhr.onload = function () {
if (xhr.status === 200 && this.readyState === 4)
{
alert(this.getAllResponseHeaders());
}
};
xhr.open('POST', '/klijentarea/klijent/SnimiNarudzbu', true);
xhr.send(Narudzba);
All of the values inside "Narudzba" are null, despite the object clearly having all the right values before being posted to controller. Help would be greatly appreciated.
You are missing Content-Type setting in your xhr request.
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
This should solve your problem.
Hope this helps!

How can I get the value of a checkbox from a for loop

My receive() function parses through data from a backend server and I use that data to create a renderHTML() function which displays the parsed data as an HTML string. I get the data to display and can also attach checkboxes perfectly fine. I am trying to get the value of questionid so that when the user clicks on the checkbox, I can use Ajax to send the values of which question was selected, which can be done by questionid. I am not sure on how to get the value of the questionid, store it, and send it through Ajax.
function receive() {
var text = document.getElementById("text").value;
var data = {
'text': text
};
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
var ourData = xhr.responseText;
var parsedData = JSON.parse(ourData);
console.log(parsedData);
renderHTML(parsedData);
}
};
xhr.open("POST", "URL", true);
xhr.send(JSON.stringify(data));
}
var questionid;
function renderHTML(data) {
var htmlString = "";
for (i = 0; i < data.length; i++) {
htmlString += "<p><input type='checkbox' value='data[i].questionid'>" +
data[i].questionid + "." + "\n";
htmlString += '</p>';
}
response.insertAdjacentHTML('beforeend', htmlString);
var t = this;
var checkboxes = document.querySelectorAll('input[type="checkbox"]');
for (var i = 0; i < checkboxes.length; i++) {
checkboxes[i].onclick = function() {
if (this.checked) {
console.log(this.questionid.value);
}
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
var Data = xhr.responseText;
console.log(Data);
var parseData = JSON.parse(Data);
};
xhr.send(JSON.stringify(data));
}
}
}
There are many ways in which you can achieve what you are looking for. For that, you will need to understand one of two concepts:
bind
closures
None of them is easy to understand for beginners but will help you vastly improve your coding skills once you get them. You can read about them here and here respectively.
The problem with your code (amongst other details) is that the value of i is global, and so by the time the DOM is rendered and the user can click in one of the checkboxes, all the checkboxes have the same value of i (the last one).
bind helps you solve this by setting an argument to the function that will always remain the same.
closures help you solve this by storing the value of a variable declared in a scope that is accessible only from a function that stores a reference to that variable.
Here is some code I wrote that does what you want using a most modern syntax, which I would highly recommend.
Specially, I would recommend you to read about the fetch api; which is a much cleaner way to make http request.
This code does what you are looking for:
function receive() {
const text = document.getElementById('text').value;
const options = {
method: 'POST',
body: JSON.stringify({ text })
}
fetch("<the url here>", options)
.then( response => response.json())
.then( data => {
renderHTML(JSON.parse(data));
})
}
function renderHTML(data){
for (const x of data) {
const content = x.questionid;
// i'm asuming that the response html element already exists
response.insertAdjacentHTML('beforeend', `<p><input value="${content}" type="checkbox">${content}</p>`);
}
document.querySelectorAll('input[type="checkbox"]').forEach( input => {
input.addEventListener((e) => {
const options = {
method: 'POST',
body: JSON.stringify(e.target.value)
};
fetch('<the second url here>', options).then( response => response.json())
.then( data => {
// 'data' is the response you were looking for.
})
})
})
}

How to post file with ajax?

Trying to save a file to a db. I am using formData via javascript to append the file and adding this as a post object via ajax. for some reason nothing gets sent.
What am I doing wrong?
HTML
<input type="file" style="display: none;" class="btn btn-primary uploadFile">
script:
$(".saveImage")
.on("click",
function() {
var files = $(".uploadFile");
var data = new FormData();
data = $.OverWatch.worker.uploadFileHandler.addUploadFiles(files, data);
$.OverWatch.worker.postUserData("/Administration/AddUserImage", data, function () {
alert("done");
});
});
Functions above look like:
addUploadFiles: function (files, data) {
$.each(files, function (i, v) {
var file = $(this).data("files");
data.append("file", file);
});
return data;
}
postUserData:
postUserData: function(url, data, callback) {
$.LoadingOverlay("show");
$.ajax({
url: url,
type: 'POST',
data: data,
cache: false,
processData: false,
contentType: false,
dataType: "HTML",
success: function(data) {
if (callback) {
callback(data);
$.LoadingOverlay("hide");
}
},
error: function(event, jqxhr, settings, thrownError) {
//$.helpers.errorHandler($("#fileDialogErrors"), event.responseText);
var h;
$.LoadingOverlay("hide");
}
});
},
backend:
public ActionResult AddUserImage()
{
if (Request.Files.Count != 0)
{
//save
}
return null;
}
edit:
var files = $(".uploadFile");
returns:
Your var file = $(this).data("files"); line of code would be returning undefined (unless you have some other javascript adding a data value, but you cannot add files to data so it in any case it would not be returning a file).
Change your loop to
$.each(files, function (i, v) {
for (i = 0; i < v.files.length; i++) {
var file = v.files[i];
data.append("file", file);
}
});
However, you can simplify this by using var data = new FormData($('form').get(0)); which will serialize all you form controls including file inputs to FormData (refer how to append whole set of model to formdata and obtain it in MVC for more information).
I also recommend you change your method signature to
public ActionResult AddUserImage(IEnumerable<HttpPostedFileBase> files)
and let the DefaultModelBinder do its magic.
you can directly get file from controller when called using Request.Files
//(Request) HttpRequestBase object for the current HTTP request
if (Request.Files.Count > 0)//// Is image is uplaod by browse button
{
var inputStream = Request.Files[0].InputStream;
using (var binaryReader = new BinaryReader(inputStream))
{
var ImageBytes = binaryReader .ReadBytes(Request.Files[0].ContentLength); // same as you can get multiple file also
}
var fileExtension = Path.GetExtension(Request.Files[0].FileName);
}
thanks.
I haven't done it with jQuery but just learned how to do it myself yesterday using plain old javascript... the following worked for me. If you want to stick with jquery maybe you can translate the functions to what you need:
var formElement = document.querySelector("form");
var payload = new FormData(formElement);
function onStateChange(ev) {
// Check if the request is finished
if (ev.target.readyState == 4) {
editor.busy(false);
if (ev.target.status == '200') {
// Save was successful, notify the user with a flash
} else {
// Save failed, notify the user with a flash
}
}
};
xhr = new XMLHttpRequest();
xhr.addEventListener('readystatechange', onStateChange);
xhr.open('POST', '/posts');
xhr.send(payload);
Maybe see if using the above code works for you (it just targets a form that you have on the same page), and then you can troubleshoot whether it's your script that's the problem or a backend / communication problem.

Waiting for two asynchonous requests

I'm having trouble sending two request in PHP and waiting for both answers. Here is my code :
function getXDomainRequest() {
var xdr = null;
if (window.XDomainRequest) {
xdr = new XDomainRequest();
} else if (window.XMLHttpRequest) {
xdr = new XMLHttpRequest({mozSystem: true});
} else {
alert("Your browser does not support AJAX");
}
return xdr;
}
function sendData() {
var json1= "";
var json2= "";
var xdr = getXDomainRequest();
xdr.onload = function() {
json1 = xdr.responseText;
}
var xdr2 = getXDomainRequest();
xdr2.onload = function() {
json2 = xdr2.responseText;
}
var Id = document.querySelector('#searchField').value;
// Call API
xdr.open("GET", "./dorequest.php?id=" + Id + "&requesttype=player");
xdr.send();
xdr2.open("GET", "./dorequest.php?id=" + Id + "&requesttype=stats");
xdr2.send();
xdr.wait();
// Display results
getHtmlResults(jsonPlayer, jsonStats);
}
As expected here the json1 and json2 are still empty when getHtmlResults is called. I could do it synchronously by calling the xdr2.send() into the xdr.onload and my final function in the xdr2.onload but I want to do it asynchronously to get a better response time.
Thanks !
(any other comment on the code is welcome I'm quite new to php :) )
EDIT :
So I tryied using Ajax and it seems to work :)
var jsonPlayer = "";
var jsonStats = "";
var steamId = document.querySelector('#searchField').value;
$.when(
$.ajax({url: "./dorequest.php?steamid=" + steamId + "&requesttype=playersummary",
success: function(response){ jsonPlayer = response; }}),
$.ajax({url: "./dorequest.php?steamid=" + steamId + "&requesttype=csgostats",
success: function(response){ jsonStats = response; }}) ).done(
function(player, stats) {
getHtmlResults(player, stats);
});
Promises are commonly used as an abstraction to deal with asynchronous processes.
Wrap your AJAX calls in a Promise to do:
var ajax1 = request("stats");
var ajax2 = request("player");
when(ajax1, ajax2).done(function (stats, player) {
console.log(stats, player);
});
Most popular frameworks have a built-in Promise API.
You can send both the calls ASync and have a function in both .onload which checks if the other request has completed. So as soon as one of the onload finds that the other onload is done, you can call the getHtmlResults function.

Categories