The problem is: I have custom analtyics engine that sends log using JavaScript. I want to send log after user submits a form. The log is send using AJAX. Now the problem is, form submission is not AJAX, it is normal request that refreshes the page.
I already learned that you can force the script executions even if client aborted connection
Does php execution stop after a user leaves the page?
What I want to learn is how to be sure that server recives request and headers if form is submited almost instantly after AJAX call is send?
var url = "...";
var my_form = document.getElementsByTagName("form")[0];
var request_received = false;
my_form.addEventListener("submit", function(e) {
if (!request_received) {
e.preventDefault(); // prevent the form from submitting
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState >= 2 && !request_received) {
request_received = true;
my_form.submit(); // submit the form only if the request has been received
}
};
xhr.open("GET", url, true);
xhr.send();
return false;
}
}, false);
Lets say that this is your form with submit button:
<form id="myForm" action="/myAction.html" method="POST">
<!-- form inputs -->
<input type="submit" value="submit me!" />
</form>
With JavaScript you can bind to the submit event of your form, do your ajax call and then return true to continue submiting your form to the server:
<script type="text/javascript">
document.getElementById('myForm').addEventListener('submit', function(e){
// do your ajax call here and when you finish, return true from
// this function (in the ajax success callback)
return true;
});
</script>
Related
I´m trying to make two POST requests to different sites:
One from the action attribute form tag , and the otherone using AJAX (specifically XMLHttpRequest) on the onsubmit event.
Here is a snippet I made that IS WORKING on chrome browser (it sends first the ajax POST and then the form post) , but IT DOESN´T work in firefox (it only sends the POST action form).
Form action POST request
<form name="form_log" method="POST" action="Site1.php" onsubmit="return validate(this);">
<input type="text" name="username">
<input type="password" name="password">
<input type="submit" name="Submit" value="Enter">
</form>
AJAX POST request
function validate(){
if(document.form_log.username.value == ""){
alert('User name is empty');
return false;
}
if(document.form_log.password.value == ""){
alert('Password is empty');
return false;
}
else{
var user=document.getElementsByName('username')[0].value;
var pass=document.getElementsByName('password')[0].value;
var parameters=`username=${user}&password=${pass}&Submit=Enter`;
var url = "http://Site2.php";
var xhttp = new XMLHttpRequest();
xhttp.open('POST',url,true);
xhttp.setRequestHeader('Content-type','application/x-www-form-urlencoded');
xhttp.onreadystatechange = ()=>{
if(xhttp.DONE && xhttp.status == 200){
console.log("SENT!");
}
}
xhttp.send(parameters);
}
}
Am I doing something wrong, and this behaviour is due to a Firefox restriction?
Thanks in advance !!
I tried this snippet on chrome and works OK! , but I can´t make to send both POST request on Firefox (it only sends the POST action request).
I've seen several posts about how to post a form using AJAX, but I am curious about options for simplification.
Here's a trimmed down version of what I'm trying:
<form id="message-form" method="POST" action="/send-message" onsubmit="return false;">
<input type="text" name="message"><br/>
<input type="text" name="phone_number"><br/>
<button type="button" onclick="return trysubmit()">Send Message</button>
</form>
<script>
function trysubmit()
{
document.getElementById("message-form").submit();
//notify user of success
//cancel the redirect
return false;
}
</script>
In this case, the form gets submitted, but the redirect still happens.
Is something like the above even possible, or do I have to manually build an AJAX request like this?
form serialize javascript (no framework)
var form = document.getElementById('message-form');
var data = new FormData(form);
var req = new XMLHttpRequest();
req.send(data);
Unless resorting to hacks like posting to a dummy target, AJAX is the way to go.
This works:
const form = document.querySelector("#message-form");
form.addEventListener("submit", event => {
event.preventDefault()
let status = "";
const data = new FormData(form);
const req = new XMLHttpRequest();
try{
req.open("POST", '/send-message');
req.send(data);
status = "success";
}
catch{
status = "failure";
}
notifyuser(status);
});
I'm not very good at programming, I'm trying to make a contact form and send the information with a response in the same page.
<form id="contact_form" method="post" action="send.php">
// fields
</form>
send.php contains a PHPMailer function to send the mail and other controls, so if js is disabled the user will be redirected to index.php with a success or error message.
But when js is active a validate function checks if all fields are filled and then start an ajax request, this is the code inside js.js file
function validate(e) {
if (error_type === 1) {
e.preventDefault();
// display errors for every fields
} else {
var url = "send.php";
var params = fileds_value;
xhttp = new XMLHttpRequest();
xhttp.open("POST", "url", true);
xhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhttp.onload = function() {
if (xhttp.readyState == 4 && xhttp.status === 200 && xhttp.responseText) {
//display success message
}
else if (xhttp.status !== 200 || !xhttp.responseText) {
//display error message
}
};
xhttp.send(JSON.stringify(params));
}
}}
window.onload = function() {
document.getElementById("contact_form").addEventListener("submit", function(e){
validate(e);
});
};
I need to send the form data with the request to prevent the page to being refreshed, right?
and in send.php
if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'XMLHttpRequest') {
header('Content-Type: application/x-www-form-urlencoded');
echo $ajax_message;
}
// else just display the message
else {
redirect_to($message);
}
But after pressing the submit button the page is realoaded and I see the PHP success message, my goal is to make the page display the success message using ajax, without reloading the page.
EDIT: #IncredibleHat I edited the code to show how the event is handled, so I have to always prevent the default behavior and send the form data like that, then in php I can get the post variables like always?
use event.preventDefault(); , at the top of your event handler, instead of wrapping it within a condition.
if your form is inside other html elements, try also event.stopPropagation(); , as it stops the event from bubbling up and being handled by listeners from parent elements
in the end you would have something like:
form.addEventListener('submit',function(){
event.preventDefault();
event.stopPropagation();
if (error_type === 1)
//doWhatever
//..... perform ajax request
})
I am trying to create a simple webpage containing comments in a table. I can successfully populate it by calling following function on "window.onload" event.
function FillCommentsTable() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var comments = JSON.parse(this.responseText);
var i = 0;
var old_tbody = document.getElementById("comments");
var new_tbody = document.createElement("tbody");
for (i = 0; i < comments.length; i++) {
var row = new_tbody.insertRow(-1);
var id = row.insertCell(0);
var user = row.insertCell(1);
var comment = row.insertCell(2);
var timestamp = row.insertCell(3);
id.innerHTML = comments[i].Id;
user.innerHTML = comments[i].User;
comment.innerHTML = comments[i].Comment;
timestamp.innerHTML = comments[i].Timestamp;
}
old_tbody.parentNode.replaceChild(new_tbody, old_tbody);
}
};
xhttp.open("GET", "API/get_comments.php", true);
xhttp.send();
}
The webpage also have functionality to submit and delete comment with simple form calling the API that manipulates the database storing the comments. The wanted functionality here is that after the submit/delete form has been submitted and called the API the page is reloaded and the table updated. To achieve this I have tried to reload the page on submit with:
<form action="API/delete_comment.php" method="post"
onsubmit="window.location.reload()">
<input type="number" name="id">
<input type="submit" value="Delete">
</form>
but this seems to have no effect except that the expected call to the API is sent. This also only occurs when trying to update the table with a form since just binding a button:
<button onclick="window.location.reload()">Load comments</button>
works as intented and updates the table correctly. Is it not possible to sent both the GET for the webpage and the POST to the API triggered on the same event or what am I missing here?
The point of AJAX is to be able to communicate with the server without having to reload the page...
Submit the form with AJAX instead and then simply call your FillCommentsTable again.
<form action="#" method="post" onsubmit="return deleteComment()">
<input type="number" name="id">
<input type="submit" value="Delete">
</form>
function deleteComment() {
var id = document.querySelector("input[name='id']");
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
FillCommentsTable();
}
};
xhttp.open("POST", "API/delete_comment.php", true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send("id="+encodeURIComponent(id.value));
return false;
}
Edit:
The above successfully sends the GET request retrieving the data. In addition to these changes I also added
new_tbody.setAttribute("id","comments");
in the FillCommentsTable function. The mistake of omitting this caused the comments table body to lose its name on the first reload which then caused subsequent calls to FillCommentTable to have no effect since there is no tbody called "comments" ...
Ideally, you should have two data call functions, one to GET data from DB and one to POST data to your DB.
function FillCommentsTable() {
//Function Stuff
}
function AddNewComment() {
//Function Stuff
}
You have a few options on how to process the data:
On POST of a new item, after you receive a status of 200, call your
FillCommentsTable function.
If you have an array storing your comments on the client side, as
you make your POST call and after you receive a status of OK,
array.push(newComment)
You can also take advantage of Promises (Browser support, ECMA2015) to ensure sequencing. I will leave it at a resource link for now as its not exactly within scope of the OP.
I've a JSP page which includes a checkbox, so when i try to submit the form using the conventional javascript way of document.forms[0].submit(); the form gets refreshed and the checkbox values are not getting retained.
Can anybody help me on how to send the form value using only AJAX. I don't need the way to send using JQuery.
This is the code I had used for sending using form submit:
function relatedAER(){
......
document.forms[0].literatureSelected.value = litNO + "&";
document.forms[0].opCode.value = "relatedAER";
document.forms[0].target='_self';
document.forms[0].action="<%=request.getContextPath()%>/litaer.do?selected="+selected;
document.forms[0].submit();
}
I hope next time, you'll put some effort, into creating even a simple code, and showing us instead of asking for a script.
Now, that bieng said: This will submit a username to a php file, called fetch.php
HTML
<input type='text' name='user' id='user' /><br/>
<input type='submit' name='submit' onclick='check()' />
<div id='output'></div>
Ajax:
function check(){
var xmlhttp;
if(window.XMLHttpRequest){
xmlhttp = new XMLHttpRequest();
}else{
xmlhttp = ActiveXObject('Microsoft.XMLHTTP');
}
xmlhttp.onreadystatechange = function(){
if(xmlhttp.readyState === 4 && xmlhttp.status === 200){
document.getElementById('output').innerHTML = xmlhttp.responseText;
}
}
get_user = document.getElementById('user').value;
param = "name="+get_user;
xmlhttp.open('POST','fetch.php', true);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp.send(param);
}
</script>