Wordpress Fetch API Admin Ajax 400 Errors - ajax

When I submit my form to my wp-admin/admin-ajax.php I get a 400 error using fetch.
I have tried removing content type.
Hard coding the Fetch URL
using FormData
let formData = new FormData(form);
Using URLSearchParams
using them both
const data = new URLSearchParams(new FormData(form));
I cant get it to work and am out of answers online so thought I'd ask here.
Can you see an error in my code?
<form >
<input type="text" name="fname">
<input type="text" name="email">
<input type="hidden" name="action" value="add_user_details_hook">
<button type="submit">Submit</button>
</form>
<script>
let form = document.forms[0];
const data = new URLSearchParams(new FormData(form));
form.addEventListener('submit', function(e){
e.preventDefault();
fetch('/wp-admin/admin-ajax.php', {
method: 'post',
body: data
})
ADMIN-AJAX.php
function ajax_add_user_details_func(){
var_dump('hey!');
}
add_action('wp_ajax_add_user_details_hook', 'ajax_add_user_details_func');
add_action('wp_ajax_nopriv_add_user_details_hook', 'ajax_add_user_details_func');
Edit I do believe it has something to do with empty FormData as even when I iterate over the object with forloop the fields are empty:
Example:
for (var [key, value] of formData.entries()) {
console.log(key, value);
}
Returns no values

Related

AJAX shows different behaviors in an if/elseif-statement which is inside the success function [duplicate]

I have looked through all the similar posts out there but nothing seems to help. This is what I have
HTML:
<section>
<form id="contact-form" action="" method="post">
<fieldset>
<input id="name" name="name" placeholder="Name" type="text" />
<input id="email" name="email" placeholder="Email" type="text" />
<textarea id="comments" name="comments" placeholder="Message"></textarea>
<div class="12u">
Send Message
Clear Form
</div>
<ul id="response"></ul>
</fieldset>
</form>
</section>
JavaScript/jQuery:
function sendForm() {
var name = $('input#name').val();
var email = $('input#email').val();
var comments = $('textarea#comments').val();
var formData = 'name=' + name + '&email=' + email + '&comments=' + comments;
$.ajax({
type: 'post',
url: 'js/sendEmail.php',
data: formData,
success: function(results) {
$('ul#response').html(results);
}
}); // end ajax
}
What I am unable to do is prevent the page refresh when the #form-button-submit is pressed. I tried return false; I tried preventDefault() and every combination including return false; inside the onClick. I also tried using input type="button" and type="submit" instead and same result. I can't solve this and it is driving be nuts. If at all possible I would rather use the hyperlink due to some design things.
I would really appreciate your help on this.
Modify the function like this:
function sendForm(e){
e.preventDefault();
}
And as comment mentions, pass the event:
onclick = sendForm(event);
Update 2:
$('#form-button-submit').on('click', function(e){
e.preventDefault();
var name = $('input#name').val(),
email = $('input#email').val(),
comments = $('textarea#comments').val(),
formData = 'name=' + name + '&email=' + email + '&comments=' + comments;
$.ajax({
type: 'post',
url: 'js/sendEmail.php',
data: formData,
success: function(results) {
$('ul#response').html(results);
}
});
});
function sendForm(){
// all your code
return false;
}
I was also bit engaged in finding solution to this problem, and so far the best working method I found was this-
Try using XHR to send request to any url, instead of $.ajax()...I know it sounds bit weird but try it out!
Example-
<form method="POST" enctype="multipart/form-data" id="test-form">
var testForm = document.getElementById('test-form');
testForm.onsubmit = function(event) {
event.preventDefault();
var request = new XMLHttpRequest();
// POST to any url
request.open('POST', some_url, false);
var formData = new FormData(document.getElementById('test-form'));
request.send(formData);
This would send your data successfully ...without page reload.
Have you tried using
function sendForm(event){
event.preventDefault();
}
Simple and Complete working code
<script>
$(document).ready(function() {
$("#contact-form").submit(function() {
$("#loading").show().fadeIn('slow');
$("#response").hide().fadeOut('slow');
var frm = $('#contact-form');
$.ajax({
type: frm.attr('method'),
url: 'url.php',
data: frm.serialize(),
success: function (data) {
$('#response').html(data);
$("#loading").hide().fadeOut('slow');
$("#response").slideDown();
}, error: function(jqXHR, textStatus, errorThrown){
console.log(" The following error occured: "+ textStatus, errorThrown );
} });
return false;
});
});
</script>
#loading could be an image or something to be shown when the form is processing, to use the code simply create a form with ID contact-form
Another way to avoid the form from being submitted is to place the button outside of the form. I had existing code that was working and created a new page based on the working code and wrote the html like this:
<form id="getPatientsForm">
Enter URL for patient server
<br/><br/>
<input name="forwardToUrl" type="hidden" value="/WEB-INF/jsp/patient/patientList.jsp" />
<input name="patientRootUrl" size="100"></input>
<br/><br/>
<button onclick="javascript:postGetPatientsForm();">Connect to Server</button>
</form>
This form cause the undesirable redirect described above. Changing the html to what is shown below fixed the problem.
<form id="getPatientsForm">
Enter URL for patient server
<br/><br/>
<input name="forwardToUrl" type="hidden" value="/WEB-INF/jsp/patient/patientList.jsp" />
<input name="patientRootUrl" size="100"></input>
<br/><br/>
</form>
<button onclick="javascript:postGetPatientsForm();">Connect to Server</button>
I expect anyone to understand my idea very well as it's a very simple idea.
give your required form itself an id or you can get it by any other way you prefer.
in the form input "submit" call an onclick method from your javascript file.
in this method make a variable refer to your from id the addEventListener on it and make a preventDefault method on "submit" not on "click".
To clarify that see this:
// element refers to the form DOM after you got it in a variable called element for example:
element.addEventListener('submit', (e) => {
e.preventDefault();
// rest of your code goes here
});
The idea in brief is to deal with the form by submit event after dealing with submit button by click event.
Whatever is your needs inside this method, it will work now without refresh :)
Just be sure to deal with ajax in the right way and you will be done.
Of course it will work only with forms.
The way I approached this: I removed the entire form tag and placed all the form elements such as input, textarea tags inside a div and used one button to call a javascript function. Like this:
<div id="myform">
<textarea name="textarea" class="form-control">Hello World</textarea>
<button type="submit" class="btn btn-primary"
onclick="javascript:sendRequest()">Save
changes</button>
<div>
Javascript:
function sendRequest() {
$.ajax({
type: "POST",
url: "/some/url/edit/",
data: {
data: $("#myform textarea").val()
},
success: function (data, status, jqXHR) {
console.log(data);
if (data == 'success') {
$(`#mymodal`).modal('hide');
}
}
});
return true;
}
I thought why use a form when we are sending the actual request using AJAX. This approach may need extra effort to do things like resetting the form elements but it works for me.
Note:
The above answers are more elegant than this but my use case was a little different. My webpage had many forms and I didn't think registering event listeners to every submit button was a good way to go. So, I made each submit button call the sendRequest() function.

Get the ID from a button which has a dynamic ID

I can not grasp my mind around this.
I am making a ajax call into a servlet. The problem is, on the page that is displayed, i could have 1-20 different buttons that needs to recall the same servlet. So I have the following form...
<form id="ajax-contact">
<input type="text" value="${item.transactionId}" id="transactionId" name="transactionId"/><br>
<input type="text" value="deliveryReceipt" id="action" name="action"/><br>
<input type="text" value="${item.id}" id="id" name="id"/><br>
<button type="submit" id="${item.id}" class="btn btn-primary" data-toggle="modal" data-target=".${item.id}">view delivery receipt</button>
</form>
In my ajax, I have this...
$(function() {
// Get the form.
var form = $('#ajax-contact');
// Get the messages div.
var formMessages = $('#form-messages');
// Set up an event listener for the contact form.
$(form).submit(function(e) {
// Stop the browser from submitting the form.
e.preventDefault();
// Serialize the form data.
//var formData = $(form).serialize();
var id = $("#id").val();
var tranid = $("#transactionId").val();
var action = $("#action").val();
var dataFromForm = "trannsactionId="+tranid+"&action="+action+"&id="+id;
alert(dataFromForm);
alert(formData);
// Submit the form using AJAX.
$.ajax({
url : "Controller",
type: "GET",
data : dataFromForm,
dataType: "json",
})
.success(function(response) {
...
I am trying to make it so the ajax call uses the params for the specific set of information within the form. How can I do this?
Thanks!
More detail:
Once this page shows, if I have 10 sections on there with a button. When I click on the first view delivery receipt button, it works fine.
If I go down my list and click on t he 8th view delivery receipt, itll make an ajax call for the first form.

Jquery ajax form submit that contains files

I have a very long form that contains files attachment:
this is how my form looks like:
The form will be submitted to this action:
[HttpPost]
public ActionResult AddReceivingConfirm(DTOreceiving entry,IEnumerable<HttpPostedFileBase> fileUpload)
{
return PartialView();
}
through ajax call which is:
$(document).on('click', 'input[type="submit"].genericSubmit', function () { //generic function for ajax submit of ANY FORMS t
if (!$("form#ValidateForm").valid()) {
return false;
};
var frmData = $('.genericForm').serialize();
var frmUrl = $('.genericForm').attr('action');
$.ajax({
type: 'post',
url: frmUrl,
data: frmData,
success: function (e) {
$('#target').html(e);
}
});
return false;
});
everything is binding perfectly except the IEnumerable<HttpPostedFileBase>which always results to null,
the file part of my form is done like this:
<tr>
<td>Attachment #1: </td>
<td colspan="3">
<input id="file1" type="file" name="fileUpload" />
</td>
</tr>
<tr>
<td>Attachment #2: </td>
<td colspan="3">
<input id="file2" type="file" name="fileUpload" />
</td>
</tr>
<tr>
<td>Attachment #3: </td>
<td colspan="3">
<input id="file3 "type="file" name="fileUpload" />
</td>
</tr>
I have tried the brackets version and etc but it won't bind.
After an hour of researching, i've read that it's not possible(?) )to do file posting conventionally through the use of Ajax unless iframe. I am not sure of what my action will be, i kinda want to avoid using plugin so i wanna know if there is some "hacky" ways to access the files directly from my form?
this is my form:
using (Html.BeginForm("AddReceivingConfirm", "Wms", FormMethod.Post, new { id = "ValidateForm", #class = "genericForm" , enctype="multipart/form-data"}))
Unfortunately the jQuery serialize() method will not include input file elements. So your files are not going to be included in the serialized value.
What you should be doing is creating a FormData object, append the files to that. You need to append the form field values as well to this same FormData object. You may simply loop through all the input field and add it. Also, in the ajax call, you need to specify processData and contentType property values to false.
$(document).on('click', 'input[type="submit"].genericSubmit', function(e) {
e.preventDefault(); // prevent the default submit behavior.
var fdata = new FormData();
$('input[name="fileUpload"]').each(function(a, b) {
var fileInput = $('input[name="fileUpload"]')[a];
if (fileInput.files.length > 0) {
var file = fileInput.files[0];
fdata.append("fileUpload", file);
}
});
// You can update the jquery selector to use a css class if you want
$("input[type='text'").each(function(x, y) {
fdata.append($(y).attr("name"), $(y).val());
});
var frmUrl = $('.genericForm').attr('action');
$.ajax({
type: 'post',
url: frmUrl,
data: fdata,
processData: false,
contentType: false,
success: function(e) {
$('#target').html(e);
}
});
});
Seems like your $.ajax needs contentType: false to prevent a bad content-type header from being inserted.
Also, if I am reading the docs ( https://api.jquery.com/serialize/ ) correctly .serialize skips file inputs...
This answer also seems helpful How can I upload files asynchronously?

How to make Dojo as generic while submitting a form?

I have the following dojo (ver 1.9) code:
require(["dojo/dom", "dojo/on", "dojo/request", "dojo/dom-form"],
function(dom, on, request, domForm){
var form = dom.byId('user_login');
var selectedTabId = showIdOfSelectedTab();
// Attach the onsubmit event handler of the form
on(form, "submit", function(evt){
// prevent the page from navigating after submit
evt.stopPropagation();
evt.preventDefault();
// Post the data to the server
request.post("login1.php", {
// Send the username and password
data: domForm.toObject("user_login"),
// Wait 2 seconds for a response
timeout: 2000
}).then(function(response) {
dom.byId(selectedTabId).innerHTML = response;
});
});
}
);
And html below:
<form name="user_login" id="user_login">
User name: <input type="text" name="user_name" id="user_name" /><br />
Password: <input type="password" name="user_password" id="user_password" /><br />
<button id="submitbutton" name="submitbutton">Submit</button>
</form>
I want to make the above dojo code as generic by sending the post action (login1.php) and the form id (i.e., user_login). I tried several ways but I could not achieve it.
Please let me know if any of you have idea.
Thanks in advance.
-Uday
This is the demo drom the dojo Tutorial right?
http://dojotoolkit.org/documentation/tutorials/1.9/ajax/
Did you get any Errormessages?
So let's see.
Have you load the dojo libary correct? If not, the widgets can't be loaded.
Must be somthing like:
src="//ajax.googleapis.com/ajax/libs/dojo/1.9.1/dojo/dojo.js">
Check the path to the login1.php.
If it's in another Folder than your code the path must be something like "../myfolder /myphp/login1.php"
Regards, Miriam

Liftweb: create a form that can be submitted both traditionally and with AJAX

Is it possible in Lift web framework to create forms (and links) that react via AJAX, but also work without Javascript support? If so, how?
When I build the form using <lift:form.ajax>, the form's action is set to javascript:// so that it no longer submits without JS. If I build the form without explicit AJAX support, I don't know how to insert the AJAX functionality.
I suppose I could build a RESTful interface (we'll have to build that anyway) and write custom Javascript to submit the form through that. I would like to avoid code duplication, though: if it is possible to handle all three inputs (RESTful, traditional HTTP POST, AJAX) with the same code, that would be best.
Take a look at http://demo.liftweb.net/form_ajax
FormWithAjax.scala
class FormWithAjax extends StatefulSnippet {
private var firstName = ""
private var lastName = ""
private val from = S.referer openOr "/"
def dispatch = {
case _ => render _
}
def render(xhtml: NodeSeq): NodeSeq =
{
def validate() {
(firstName.length, lastName.length) match {
case (f, n) if f < 2 && n < 2 => S.error("First and last names too short")
case (f, _) if f < 2 => S.error("First name too short")
case (_, n) if n < 2 => S.error("Last name too short")
case _ => S.notice("Thanks!"); S.redirectTo(from)
}
}
bind( "form", xhtml,
"first" -> textAjaxTest(firstName, s => firstName = s, s => {S.notice("First name "+s); Noop}),
"last" -> textAjaxTest(lastName, s => lastName = s, s => {S.notice("Last name "+s); Noop}),
"submit" -> submit("Send", validate _)
)
}
form_ajax.html
<lift:surround with="default" at="content">
Enter your first and last name:<br>
<form class="lift:FormWithAjax?form=post">
First Name: <form:first></form:first>
Last Name: <form:last></form:last>
<form:submit></form:submit>
</form>
</lift:surround>
And this will work without javascript:
<form action="/form_ajax" method="post">
<input name="F1069091373793VHXH01" type="hidden" value="true">
First Name: <input value="" type="text" name="F1069091373788OVAAWQ" onblur="liftAjax.lift_ajaxHandler('F1069091373789N2AO0C=' + encodeURIComponent(this.value), null, null, null)">
Last Name: <input value="" type="text" name="F1069091373790VANYVT" onblur="liftAjax.lift_ajaxHandler('F1069091373791CJMQDY=' + encodeURIComponent(this.value), null, null, null)">
<input name="F1069091383792JGBYWE" type="submit" value="Send">
</form>
I dont know a lot about Lift so my answer focuses on alternate way to do it.
This is jQuery based and will do with AJAX when Javascript is usable and traditional POST if there is no Javascript support enabled.
Form:
<form id="ajaxform" action="formhandler.php" method="post" enctype="multipart/form-data" >
<input name="firstname" type="text" />
<input name="email" type="email" />
<input name="accept" type="submit" value="Send" />
</form>
<div id="result"></div>
JS:
note: jQuery $.ajax() sends as application/x-www-form-urlencoded by default, it may be good to set form enctype="application/x-www-form-urlencoded" too.
$("#ajaxform").submit(function(e){
// Alternative way to prevent default action:
e.preventDefault();
$.ajax({
type: 'POST',
url: 'formhandler.php',
// Add method=ajax so in server side we can check if ajax is used instead of traditional post:
data: $("#ajaxform").serialize()+"&method=ajax",
success: function(data){ // formhandler.php returned some data:
// Place returned data <div id="result">here</div>
$("#result").html(data);
}
});
// Prevent default action (reposting form without ajax):
return false;
});
Server side (PHP)
<?php
if (isset($_POST['method']) && $_POST['method'] == 'ajax') {
// AJAX is used this time, only #result div is updating in this case.
} else {
// Traditional POST is used to send data, whole page is reloading. Maybe send <html><head>... etc.
}
?>
What About REST then?
This is something you should decide to use or to not use, it is not something to support as alternate to other methods (ajax, traditional) but more something integrate within other methods.
Of course you can always enable or disable REST feature.
You can always make form method="POST/GET/PUT/DELETE" and ajax call RESTful:
...
$.ajax({
type: 'PUT',
url: 'formhandler.php',
...
...
$.ajax({
type: 'DELETE',
url: 'formhandler.php',
...
But REST asks us to use XML, JSON, ... for requests too
Well, that is not well supported by browsers (without Javascript) but $.ajax() uses application/x-www-form-urlencoded as default encoding.
Ofcourse, with Javascript one can always convert data container to XML or JSON ...
Here's how it can be done with jQuery, JSON object:
/* This is function that converts elements to JSON object,
* $.fn. is used to add new jQuery plugin serializeObject() */
$.fn.serializeObject = function()
{
var o = {};
var a = this.serializeArray();
$.each(a, function() {
if (o[this.name]) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
} else {
o[this.name] = this.value || '';
}
});
return o;
};
But I want one AJAX call that does everything:
You are right, computers should do our work. It's what they are designed for.
So, another thing that needs to be done is to check what http method our original html form wants to use and adapt it to send ajax requests with same method that would be used without javascript support.
This is modified version from under JS: heading used earlier:
...
// Alternative way to prevent default action:
e.preventDefault();
// Find out what is method that form wants to use and clone it:
var restmethod = $('#ajaxform').attr('method');
// Put form data inside JSON object:
var data = $('#orderform').serializeObject();
// Add method=ajax so in server side we can check if ajax is used instead of traditional post:
data.method = 'ajax';
$.ajax({
type: restmethod, // Use method="delete" for ajax if so defined in <form ...>
url: 'formhandler.php',
data: data, // data is already serialized as JSON object
...
Now, our AJAX handler sends data as JSON object using method (post|get|put|delete) that is defined at <form method="put" ...>, if form method changes then our ajax handler will adapt changes too.
That's all, some code tested and is actually in use, some is not tested at all but should work.

Resources