Just started with JQuery for AJAX calls and what I thought would be a simple script has had me baffled two days now. Basically I want the form data POSTed to the server, and if data entered by user okay then a "Thank You" message is returned, or a message is returned to say there are errors.
In both events, it's HTML that I want returned. This is happening however, when there are errors in the form data, and the form is submitted again, there is a page refresh (I know this as hitting F5 produces the browsers default dialogue box asking to SEND or CANCEL).
This page refresh only happens once submitted the form (the HTML returned from server on initial AJAX call) a second time. Otherwise there appears to be no other faults. The data entered by user and sent to server by the initial AJAX call is okay too.
It's just what happens after server send the HTML back to the client when there are errors. I've posted the code and HTML below, any thoughts would really be welcome at this moment as I'm really new to this JQuery / AJAX stuff!
<!-- found on the contact page -->
<script type="text/javascript">
$(document).ready( function() {
$( '#submit' ).click( function() {
var payload = $( '#form' ).serialize();
// var name = $('input[name=name]');
// var data = 'name=' + name.val();
$.ajax({
url: '/contact/post/',
type: 'post',
data: payload,
cache: false,
success: function( html ) { console.log( html );
$( '#formbox' ).html( html );
}
});
return false;
}); // close of #submit
});
</script>
<!-- ... ... -->
<div id="formbox">
<form
id="form"
method="post"
accept-charset="utf-8"
action="#">
<!-- using only one field at the moment (debugging purposes) -->
<div class="lft"><p><label for="_name">Name</label> </p></div>
<div class="rgt"><p> <input type="text" id="_name" name="name" size="16" maxlength="32" value="Elizabeth Q" /></p></div>
<div class="lft"><p> </p></div>
<div class="rgt"><p>
<input type="submit" id="submit" name="submit" value="Send Message" />
</p></div>
</form>
</div>
<!-- what is returned from server if no errors with user data -->
<div class="both">
<p>Thank you for contacting us, please expect a prompt reply shortly.</p>
</div>
<!-- what is returned from server if there are errors with user data -->
<form
id="form"
method="post"
accept-charset="utf-8"
action="#">
<div class="both">
<p class="error">Please amend the following error(s) shown below before trying again.</p>
<br />
<ul>
<?php foreach( $this -> get( 'logger' ) -> export() as $error ): ?>
<li><p><?php echo $error; ?></p></li>
<?php endforeach; ?>
</div>
<div class="lft"><p><label for="_name">Name</label> </p></div>
<div class="rgt"><p> <input type="text" id="_name" name="name" size="16" maxlength="32" value="<?php echo $this -> get( 'name' ); ?>" /></p></div>
<div class="lft"><p> </p></div>
<div class="rgt"><p>
<input type="submit" id="submit" name="submit" value="Send Message" />
</p></div>
</form>
<!-- the php file that determines user data is valid or not and returns response -->
final class QPage_Handler_Ajax extends QPage_Handler_Validator {
public function __construct() {
$this -> initialise();
$this -> id = 'site';
}
public function execute( QDataspace_Interface $dataspace ) {
if( !$this -> validate( $request = QRegistry::get( 'request' ), QRegistry::get( 'logger' ) ) ) {
// execute this handler as errors found
$this -> handler -> execute( $dataspace );
} else {
// no errors with data sent to server
$page = new QPage_View( $request = QRegistry::get( 'request' ) );
$page -> render( 'contact/post/body.tpl' );
}
}
protected function initialise() {
$this -> forward( new QPage_Handler_Ajax_Success() );
$this -> addCondition( QValidator::factory()
-> addCondition( new QValidator_Condition_Required( 'name', 'The field "name" is required.' ) )
-> addCondition( new QValidator_Condition_Expression( 'name', '/^[a-zA-Z ]+$/', 'The field "name" has illegal character(s).' ) )
-> addCondition( new QValidator_Condition_Size_Maximum( 'name', 32, 'The field "name" must not exceed 32 characters.' ) )
);
}
}
final class QPage_Handler_Ajax_Success extends QPage_Handler {
public function __construct() {
$this -> id = 'site';
}
public function execute( QDataspace_Interface $dataspace ) {
$page = new QPage_View( $request = QRegistry::get( 'request' ) );
$page -> set( 'logger', QRegistry::get( 'logger' ) );
$page -> render( 'contact/post/error.tpl' );
}
}
Any suggestions to how to fix the issue(s) that I have are very much welcome and appreciated. Please remember I am new to using JQuery but I've been using PHP for a number of years.
This is merely a JavaScript/jQuery problem.
On page load, you are running the jQuery code which binds the click on the submit button. Then, when clicking the submit button and an error occurs, you are returning from PHP the whole form again (unlike in the case of a successful POST, where you are only returning the success message).
The problem here is that, according to jQuery, the old submit button on which the click event was binded has been removed. and replaced by a new button.
Several solution can be done with this, some are a bad choice, others are better. What I would recommend is the following:
Instead of returning the whole form, return only the error message and prepend it to the form.
<div class="both">
<p class="error">Please amend the following error(s) shown below before trying again.</p>
<br />
<ul>
<?php foreach( $this -> get( 'logger' ) -> export() as $error ): ?>
<li><p><?php echo $error; ?></p></li>
<?php endforeach; ?>
</div>
P.S. I would change $( '#submit' ).click( function() {
to $("#form").submit(function(){
as this will be fired even if the form was submitted in a different manner, such as clicking Enter in a text field.
A small tip is to return JSON with AJAX from PHP, it will help you accomplish this task in a much easier manner.
Another solution is to use .live() .on()
This is the easy way out, but I do not recommend this.
$(document).ready( function() {
// this can also be replaced by: $('#formbox').on('click', '#submit', function() {
$('#formbox').on('submit', '#form', function(){
var payload = $('#form').serialize();
// var name = $('input[name=name]');
// var data = 'name=' + name.val();
$.ajax({
url: '/contact/post/',
type: 'post',
data: payload,
cache: false,
success: function(html) {
console.log(html);
$('#formbox').html(html);
}
});
return false;
}); // close of #submit
});
EDIT:
.live()
was deprecated since jQuery 1.7, and removed since jQuery 1.9