No Javascript Fallback for AJAX Form submission - javascript

I am new to AJAX and am in the process of converting some regular HTML forms to AJAX.
My existing implementation is as follows - form (on page1.php) posts to page2.php which does some validation on post data and redirects to an error page if something is missing. If the input is fine, it includes page3.php which processes the request and redirects back to page1.php.
php/page1.php
<form method="post" action="/php/page2.php" >
<input type="text" name="input1" placeholder="Howdy..." />
<input type="text" name="input2" placeholder="Howdy..." />
<input type="submit" value="Submit" />
</form>
php/page2.php
<?php
// perform some validation on inputs
if (empty($_POST['input1']))
{
$location ='Location: /php/error.php';
header($location);
exit;
}
// Inputs are fine
include('/php/page3.php');
?>
page3.php
<?php
// do some form processing
// redirect back to page1.php
$location = 'Location: /php/page1.php";
header($location);
exit;
?>
To convert to AJAX, I am using #SSL's solution on this SO link How to show loading gif when request goes Ajax
http://jsfiddle.net/clickthelink/Uwcuz/1/
The error from validation and success page are both displayed back on page1.php via the callback function.
php/page2.php
<?php
// perform some validation on inputs
if (empty($_POST['input1']))
{
// Echo erorr code isntead of redirect
echo "Please enter input1";
return;
//$location ='Location: /php/error.php';
//header($location);
//exit;
}
// Inputs are fine
include('/php/page3.php');
?>
page3.php
<?php
// do some form processing
// Echo success instead of redirect
echo "SUCCESS";
// redirect back to page1.php
//$location = 'Location: /php/page1.php";
//header($location);
//exit;
?>
This part is working fine.
My question (finally) is how do I handle users who have javascript disabled? I know the form will get submitted appropriately but I wont get the redirect back in case of the error or success. I would like to retain header() redirect type of functionality in this case also. Is this possible? I would appreciate the help.

You want to detect if this is an xhr request, and default to the non-ajax behavior if it is not.
I would look at $_SERVER['HTTP_X_REQUESTED_WITH']

Keep your current form setup as-is, if it is working for you without javascript.
For javascript enabled browsers you can hijack the 'submit' event on the form. Capture the event and post the form, via ajax, to scripts/pages that handle and return the data in a javascript-friendly format for final consumption.
For example, using jquery:
<form method="post" action="/php/page2.php" id="js-form" >
<input type="text" name="input1" placeholder="Howdy..." />
<input type="text" name="input2" placeholder="Howdy..." />
<input type="submit" value="Submit" />
</form>
<script>
$(document).ready(function(){
$('#js-form').on('submit',function(e){
// logic to submit ajax form and handle response
// return false to cancel native browser form submission.
return false;
});
});
</script>
Another idea is to keep the pages you already have, but send a flag with the ajax request to disable the browser redirect headers. For example, add 'src=ajax' when submitting the form via ajax. Then in the script use logic to say:
<?php
if( !empty($_REQUEST['src'] && $_REQUEST['src'] == 'ajax' ) {
// add redirect logic here.
}
?>

Related

How to prevent data submission after refresh [duplicate]

I think that this problem occurs often on a web application development. But I'll try to explain in details my problem.
I'd like to know how to correct this behavior, for example, when I have a block of code like this :
<?
if (isset($_POST['name'])) {
... operation on database, like to insert $_POST['name'] in a table ...
echo "Operation Done";
die();
}
?>
<form action='page.php' method='post' name="myForm">
<input type="text" maxlength="50" name="name" class="input400" />
<input type="submit" name="Submit" />
</form>
When the form gets submitted, the data get inserted into the database, and the message Operation Done is produced. Then, if I refreshed the page, the data would get inserted into the database again.
How this problem can be avoided? Any suggestion will be appreciated :)
Don't show the response after your create action; redirect to another page after the action completes instead. If someone refreshes, they're refreshing the GET requested page you redirected to.
// submit
// set success flash message (you are using a framework, right?)
header('Location: /path/to/record');
exit;
Set a random number in a session when the form is displayed, and also put that number in a hidden field. If the posted number and the session number match, delete the session, run the query; if they don't, redisplay the form, and generate a new session number. This is the basic idea of XSRF tokens, you can read more about them, and their uses for security here: http://en.wikipedia.org/wiki/Cross-site_request_forgery
Here is an example:
<?php
session_start();
if (isset($_POST['formid']) && isset($_SESSION['formid']) && $_POST["formid"] == $_SESSION["formid"])
{
$_SESSION["formid"] = '';
echo 'Process form';
}
else
{
$_SESSION["formid"] = md5(rand(0,10000000));
?>
<form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>" method="post">
<input type="hidden" name="formid" value="<?php echo htmlspecialchars($_SESSION["formid"]); ?>" />
<input type="submit" name="submit" />
</form>
<?php } ?>
I ran into a similar problem. I need to show the user the result of the POST. I don't want to use sessions and I don't want to redirect with the result in the URL (it's kinda secure, I don't want it accidentally bookmarked). I found a pretty simple solution that should work for the cases mentioned in other answers.
On successfully submitting the form, include this bit of Javascript on the page:
<script>history.pushState({}, "", "")</script>
It pushes the current URL onto the history stack. Since this is a new item in history, refreshing won't re-POST.
UPDATE: This doesn't work in Safari. It's a known bug. But since it was originally reported in 2017, it may not be fixed soon. I've tried a few things (replaceState, etc), but haven't found a workaround in Safari. Here are some pertinent links regarding the issue:
Safari send POST request when refresh after pushState/replaceState
https://bugs.webkit.org/show_bug.cgi?id=202963
https://github.com/aurelia/history-browser/issues/34
Like this:
<?php
if(isset($_POST['uniqid']) AND $_POST['uniqid'] == $_SESSION['uniqid']){
// can't submit again
}
else{
// submit!
$_SESSION['uniqid'] = $_POST['uniqid'];
}
?>
<form action="page.php" method="post" name="myForm">
<input type="hidden" name="uniqid" value="<?php echo uniqid();?>" />
<!-- the rest of the fields here -->
</form>
I think it is simpler,
page.php
<?php
session_start();
if (isset($_POST['name'])) {
... operation on database, like to insert $_POST['name'] in a table ...
$_SESSION["message"]="Operation Done";
header("Location:page.php");
exit;
}
?>
<html>
<body>
<div style='some styles'>
<?php
//message here
echo $_SESSION["message"];
?>
</div>
<form action='page.php' method='post'>
<!--elements-->
</form>
</body>
</html>
So, for what I needed this is what works.
Based on all of the above solutions this allows me to go from a form to another form, and to the n^ form , all the while preventing the same exact data from being "saved" over and over when a page is refreshed (and the post data from before lingers onto the new page).
Thanks to those who posted their solution which quickly led me to my own.
<?php
//Check if there was a post
if ($_POST) {
//Assuming there was a post, was it identical as the last time?
if (isset($_SESSION['pastData']) AND $_SESSION['pastData'] != $_POST) {
//No, Save
} else {
//Yes, Don't save
}
} else {
//Save
}
//Set the session to the most current post.
$_session['pastData'] = $_POST;
?>
We work on web apps where we design number of php forms. It is heck to write another page to get the data and submit it for each and every form. To avoid re-submission, in every table we created a 'random_check' field which is marked as 'Unique'.
On page loading generate a random value and store it in a text field (which is obviously hidden).
On SUBMIT save this random text value in 'random_check' field in your table. In case of re-submission query will through error because it can't insert the duplicate value.
After that you can display the error like
if ( !$result ) {
die( '<script>alertify.alert("Error while saving data OR you are resubmitting the form.");</script>' );
}
No need to redirect...
replace die(); with
isset(! $_POST['name']);
, setting the isset to isset not equal to $_POST['name'], so when you refresh it, it would not add anymore to your database, unless you click the submit button again.
<?
if (isset($_POST['name'])) {
... operation on database, like to insert $_POST['name'] in a table ...
echo "Operation Done";
isset(! $_POST['name']);
}
?>
<form action='page.php' method='post' name="myForm">
<input type="text" maxlength="50" name="name" class="input400" />
<input type="submit" name="Submit" />
</form>
This happen because of simply on refresh it will submit your request again.
So the idea to solve this issue by cure its root of cause.
I mean we can set up one session variable inside the form and check it when update.
if($_SESSION["csrf_token"] == $_POST['csrf_token'] )
{
// submit data
}
//inside from
$_SESSION["csrf_token"] = md5(rand(0,10000000)).time();
<input type="hidden" name="csrf_token" value="
htmlspecialchars($_SESSION["csrf_token"]);">
I think following is the better way to avoid resubmit or refresh the page.
$sample = $_POST['submit'];
if ($sample == "true")
{
//do it your code here
$sample = "false";
}

How would you design this webpage with multiple forms?

I currently have a simple php/html page with only one form, where the user inputs a number, then the page loads itself (but this time with parameters).
Some key codelines :
<form action="index.php" method="get">
<input type="text" name="name">
<input type="submit" value="Submit">
</form>
<?php
if (!isset ($_GET["name"])) {
echo "<div> Adding some content related to the input </div>";
}
?>
Now i'm looking forward adding 3 more fields, and split my page for each form.
The user should be free to use the 4 forms separately, I don't want to have the page reload every time. I'm unsure how to design this page - should i rework my page and work with JS ?
I have basic knowledge with PHP, a little with JS. I will be able to google up most things i need but first i need a proper direction :) thanks !
you can use AJAX for this purpose...
$(document).ready(function() {
// process the form
$('form').submit(function(event) {
// get the form data
// there are many ways to get this data using jQuery (you can use the class or id also)
var formData = {
'name' : $('input[name=name]').val(),
'email' : $('input[name=email]').val(),
};
// process the form
$.ajax({
type : 'POST', // define the type of HTTP verb we want to use (POST for our form)
url : 'process.php', // the url where we want to POST
data : formData, // our data object
dataType : 'json', // what type of data do we expect back from the server
encode : true
})
// using the done promise callback
.done(function(data) {
// log data to the console so we can see
console.log(data);
// here we will handle errors and validation messages
});
// stop the form from submitting the normal way and refreshing the page
event.preventDefault();
});
});
AJAX is a must if you don't want the page to reload between each interaction.
If you have trouble with it and want to opt for just PHP (with page reloads) you can handle multiple forms on one page easily enough - my preferred method is to set a hidden value in the form called 'action' settings its value & reading this in again when the page loads for example:
<?php if(isset($_POST['action']))
{
$action = $_POST['action'];
switch ($action)
{
case 'hello':
echo 'hello';
break;
case 'bye':
echo 'bye';
break;
}
}
?>
<form method="post" action="Untitled-5.php">
<input type="hidden" name="action" value="hello"/>
<input type="submit" value="hello"/>
</form>
<form method="post" action="Untitled-5.php">
<input type="hidden" name="action" value="bye"/>
<input type="submit" value="bye"/>
</form>
You could then save and echo out the values for each form each time keeping them updated as the user interacts with each of the forms.
AJAX is the nicer solution however
If you do not want to reload the page every time you submit each form then you should use Ajax for calling your api. You write the separate api in PHP, and then call that api in Jquery's Ajax.
Here the page won't be reloaded. Also you can call the ajax on each of the button click.

Getting an Ajax response from a form.submit() to PHP

I'm trying to combine a form.submit() call with a jquery/ajax call to get a response from my php login script - I've just spent a few hours trying to hack together some of the hundreds of posts/examples on a similar topic but am out of ideas now so am hoping someone can help.
My sign in form looks like this...
<form id ="signInForm" action= "/userManagement/proxy_process_login.php" method="post" name="login_form">
<input required id="signInUserId" name="email" type="text" placeholder="Username/Email" class="input-medium">
<input required id="signInPassword" name="password" type="password" placeholder="Password" class="input-medium">
<button id="signin" name="signin" class="btn btn-success" onclick="signInSubmit(this.form, this.form.signInPassword);">Sign In</button>
</form>
The function signInSubmit() (called by the button's onclick) simply validates the text fields, and replaces the plain text password with a hashed version before finally calling "form.submit()", like this...
//ommited a bunch of text input validation
var p = document.createElement("input");
form.appendChild(p);
p.name = "p";
p.type = "hidden";
p.value = hex_sha512(password.value);
password.value = ""; // Make sure the plaintext password doesn't get sent.
form.submit();
My PHP script (proxy_process_login) also works fine before adding any jquery/ajax and essentially does this...
if (login($email, $password, $mysqli) == true) {
// Login success (ok to reload existing page)
header("Location: ../index.php?login=success");
exit();
} else {
// Login failed (do NOT want to reload page - just message "fail" back via AJAX so I can update page accordingly)
echo "fail";
exit();
}
But given the route I'm taking to submit the form, I'm struggling to incorporate an Ajax example - because I've got this new "form" variable (with the hashed p variable appended), so I can't use an Ajax call which refers back to the form using jquery like this...
$.ajax({type:'POST', url: '/userManagement/proxy_process_login.php', data:$('#signInForm').serialize(), success: function(response) {
console.log(response);
}});
(because the jquery reference doesn't include the new variable, and I've already specified the php script in the action attribute of my form)
And I also can't call something like "serialize()" on my "form" variable inside signInSubmit().
Any ideas on an appropriate way to structure a solution to this?! Thanks!
Unfortunately there is no callback for native form submission using action attribute , it was used in the past to redirect you to that page and show the results there.
Modern method now is to use ajax call , after perventingthe default submission.
Solution:
HTML:
<form id="myForm">
<!-- form body here --!>
</form>
Javascript:
$("#myForm").submit(function(e){
e.preventDefault();//prevent default submission event.
//validate your form.
//disable your form for preventing duplicate submissions.
//call you ajax here.
//upon ajax success reset your form , show user a success message.
//upon failure you can keep your fields filled , show user error message.
})
this is a typical algorithm i use in any project i do , i recommend using parsley JS for front-end validation.

Change page after submitting the form using javascript

I have a form that after submitting goes to page "http://qwertyasdfgh.rozblog.com/New_Post" ( the action value )
I don't want to change the action but I want to redirect to another page after submitting.
I tried to redirect to "http://qwerty.rozblog.com/page/success" after submitting but it doesn't work .
here is the code I tried :
(html)
<form method="post" action="http://qwertyasdfgh.rozblog.com/New_Post" id="f1">
<input type="text" name="title" style="width:300px"><br />
<input type="text" name="pimg" style="width:300px" maxlength="3072"><br />
<textarea dir="rtl" id="post" name="post" style="width:300px;" aria-hidden="true"></textarea><br />
<input type="submit" name="postsubmit" value=" submit " style="background:#333;" onclick="location()">
</form>
(js)
function location() {
window.location.replace("http://qwerty.rozblog.com/page/success");
}
and here is the fiddle
You can submit the form using jquery and AJAX (or I misunderstood you):
$('#f1').submit(function(e)
{
e.preventDefault();
$.post('http://qwertyasdfgh.rozblog.com/New_Post',
formDataAsJSON, //use eg. jquery form plugin
function(data)
{
window.location = 'somewhere';
}
);
});
You have two choices.
1) Submit that form using AJAX and after recieving response from server redirect browser to your desired page. You can use for example jQuery with Ajax form plugin. The code would look like this:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.js"></script>
<script src="http://malsup.github.com/jquery.form.js"></script>
<script>
// wait for the DOM to be loaded
$(document).ready(function() {
// bind 'f1' form and provide a simple callback function
$('#f1').ajaxForm(function() {
window.location = "/page/success"
});
});
</script>
OR
2) You can leave your form and js as is, and use for example php to redirect user after doing some stuff.
New_post.php
<?php
// some stuff without printing (you cant change headers if you print something)
Header("Location: /page/success");
If possible, you can configure /New_Post to redirect to /page/success using meta refreshing in head:
<meta http-equiv="refresh" content="0; url=http://qwerty.rozblog.com/page/success">

How do I process forms (front and back end) on the same page?

I currently have a form that looks like this (using Bootstrap):
I've traditionally processed the form via post to another php file like so
<form action="complete.php" method="post" class="form-inline" role="form">
However, it kind of ruins the user experience when they're taken to a different page, and I've seen something before, where after submitting a form, the text just changed if it was valid. So, the text and form of the above image might just be replaced with "Thank you, your email has been accepted" if they offer a valid email.
So this question is two-part:
First, how do I do this on the backend? I'm using php for simplicity since it was so easy to install.
Second, how do I do this on the front end? Is there a common reference term for this kind of action in JS?
Answering either part of this (both if you can!) would be wonderful. If you have reference documents for me that aren't too complicated (I'm new to this), I'd be more than happy to read them too.
Thank you!
I'm going to extend on what Sam Sullivan said about the Ajax method.
Ajax basically runs any script in the background, making it virtually unnoticeable to the user. Once the script runs you can return a boolean or string to check if the result is true or false.
JS:
function validateForm(){
$.ajax({
type: 'POST',
url: '/path/to/processForm.php',
data: $('#yourForm').serialize(),
success: function(output){
if(output){ // You can do whatever JS action you want in here
alert(output);
}else{
return true; // this will redirect you to the action defined in your form tag, since no output was found.
}
}
});
return false;
}
Then in your processForm.php script, you validate the data through $_POST. Whatever you echo out in this script, will be your output.
For more, http://api.jquery.com/jquery.ajax/
Either include the PHP and form logic on the same page:
<?php
if(isset($_POST['submit'])) {
// Submit logic
echo 'Success';
}
?>
<form action="" method="POST">
<!-- etc -->
<input type="submit" name="submit" value="Submit" />
</form>
Or you can submit it with AJAX:
<form action="" method="POST" onsubmit="submitForm(this); return false;">
<!-- etc -->
<input type="submit" name="submit" value="Submit" />
</form>
<script type="text/javascript">
function submitForm(form)
{
// This can use AJAX to submit the values to a PHP script
}
</script>
If you have jQuery, you don't need to use an inline event handler (which is better):
<script type="text/javascript">
$('form').submit(function(event) {
event.preventDefault();
$form = $(event.target);
// AJAX here
});
</script>
This should be enough to get started..let me know if you have specific questions.
Change the form to
<form action="[whatever the page name is]" method="post" class="form-inline" role="form">
First, how do I do this on the backend? I'm using php for simplicity since it was so easy to install.
At the top of the page, add
<?php
if(isset($_POST)){
// Check for the $_POST variables and process
// $content = "<div> ... </div>" // Then echo out the content in place of the original for
}
?>
You can just put form action="filename-of-the-form-processor" or leave it blank for same page. If you can't avoid to put php module on the same page where your form reside make a view.php file then just include it.
index.php <- where form process happends
index.view.php <- where form tags reside so you will have a cleaner line of codes.
Note: this is not the best way to do it.

Categories

Resources