Robert Granlund
asked on
PHP and jQuery
I have a form that when submitted, if it is successful I want to show a certain div and hide another div. It works on success but then reverts back to the original once the page resets. I'm not sure how to do this. Where I am trying to implement the jQuery is on line: 43 - 51
<?php
if (isset($_POST['submitted'])) { // Handle the form.
// Trim all the incoming data:
$trimmed = array_map('trim', $_POST);
$errors = array(); // Initialize an error array.
// Check for a first name:
if (preg_match('/^[A-Z \'.-]{2,20}$/i', $trimmed['full_name'])) {
$fn = mysqli_real_escape_string($dbc, $trimmed['full_name']);
} else {
$errors[] = 'You forgot to enter your name.';
}
// Check for an email address:
if (preg_match('/^[\w.-]+@[\w.-]+\.[A-Za-z]{2,6}$/', $trimmed['email'])) {
$e = mysqli_real_escape_string($dbc, $trimmed['email']);
} else {
$errors[] = 'You forgot to enter a valid email address.';
}
if (empty($errors)) {
// Make sure the email address is available:
$q = "SELECT user_id FROM jmc_cal_users WHERE email='$e'";
$r = mysqli_query($dbc, $q) or trigger_error("Query: $q\n<br />MySQL Error: " . mysqli_error($dbc));
if (mysqli_num_rows($r) == 0) { // Available.
// Create the activation code:
$a = md5(uniqid(rand(), true));
// Add the user to the database:
$q = "INSERT INTO jmc_cal_users (email, full_name, active, registration_date) VALUES ('$e', '$fn', '$a', NOW() )";
$r = mysqli_query($dbc, $q) or trigger_error("Query: $q\n<br />MySQL Error: " . mysqli_error($dbc));
if (mysqli_affected_rows($dbc) == 1) { // If it ran OK.
// Send the email:
$body = "Thank you for registering your email please click on this link:\n\n";
$body .= BASE_URL . 'activate.php?x=' . urlencode($e) . "&y=$a";
mail($trimmed['email'], 'Email Confirmation', $body, 'From: admin@sitename.com');
?>
<script>
$(function () {
$("#calc_submit").click(function () {
$(".submit-cont").hide("slow");
$(".calculator-statement").show("slow");
});
});
</script>
<?php
} else { // If it did not run OK.
echo '<p class="error">Your email could not be registered due to a system error. We apologize for any inconvenience.</p>';
}
} else { // The email address is not available.
echo '<p class="error">That email address has already been registered.</p>';
}
} else { // Report the errors.
echo '<h1>Error!</h1>
<p class="error">The following error(s) occurred:<br />';
foreach ($errors as $msg) { // Print each error.
echo " - $msg<br />\n";
}
echo '</p><p>Please try again.</p><p><br /></p>';
} // End of if (empty($errors)) IF.
mysqli_close($dbc);
} // End of the main Submit conditional.
?>
<html>
<form action="?" method="post">
<div class="calculator-submit">
<p>
<input type="text" name="full_name" size="25" maxlength="120" value="<?php if (isset($trimmed['full_name'])) echo $trimmed['full_name']; ?>" placeholder="Name"/>
<br />
<input type="email" name="email" size="25" maxlength="65" value="<?php if (isset($trimmed['email'])) echo $trimmed['email']; ?>" placeholder="Email"/>
</p>
<p>
</p>
</div>
<div class="submit-cont">
<input type="submit" name="submit" id="calc_submit" value="Submit" />
<input type="hidden" name="submitted" value="TRUE" />
</div>
</form>
<div>
<!-- END Calculator Submit Form -->
<div class="calculator-statement" style="display:none;">
<h2>Check your email</h2><br />
</div>
</html>
ASKER
How would I send a "signal" to the jQuery upon success?
jQuery has HTTP request methods that invoke success or failure functions. But that aside, it might be simpler to just work with the server-side response, as shown in this article.
https://www.experts-exchange.com/articles/10712/The-Hello-World-Exercise-with-jQuery-and-PHP.html
Your jQuery code could look for information in the AJAX response and decide what to do. A good response format is JSON because it's a nearly universal language in information processing today.
https://www.experts-exchange.com/articles/10712/The-Hello-World-Exercise-with-jQuery-and-PHP.html
Your jQuery code could look for information in the AJAX response and decide what to do. A good response format is JSON because it's a nearly universal language in information processing today.
This is typically what you use ajax for. So instead of submitting the page the traditional way, you submit behind the scenes asynchronously.
This is untested but demonstrates the use of ajax:
This is untested but demonstrates the use of ajax:
<?php
if (isset($_POST['submitted'])) { // Handle the form.
// Trim all the incoming data:
$trimmed = array_map('trim', $_POST);
$errors = array(); // Initialize an error array.
// Check for a first name:
if (preg_match('/^[A-Z \'.-]{2,20}$/i', $trimmed['full_name'])) {
$fn = mysqli_real_escape_string($dbc, $trimmed['full_name']);
} else {
$errors[] = 'You forgot to enter your name.';
}
// Check for an email address:
if (preg_match('/^[\w.-]+@[\w.-]+\.[A-Za-z]{2,6}$/', $trimmed['email'])) {
$e = mysqli_real_escape_string($dbc, $trimmed['email']);
} else {
$errors[] = 'You forgot to enter a valid email address.';
}
if (empty($errors)) {
// Make sure the email address is available:
$q = "SELECT user_id FROM jmc_cal_users WHERE email='$e'";
$r = mysqli_query($dbc, $q) or trigger_error("Query: $q\n<br />MySQL Error: " . mysqli_error($dbc));
if (mysqli_num_rows($r) == 0) { // Available.
// Create the activation code:
$a = md5(uniqid(rand(), true));
// Add the user to the database:
$q = "INSERT INTO jmc_cal_users (email, full_name, active, registration_date) VALUES ('$e', '$fn', '$a', NOW() )";
$r = mysqli_query($dbc, $q) or trigger_error("Query: $q\n<br />MySQL Error: " . mysqli_error($dbc));
if (mysqli_affected_rows($dbc) == 1) { // If it ran OK.
// Send the email:
$body = "Thank you for registering your email please click on this link:\n\n";
$body .= BASE_URL . 'activate.php?x=' . urlencode($e) . "&y=$a";
mail($trimmed['email'], 'Email Confirmation', $body, 'From: admin@sitename.com')
} else { // If it did not run OK.
$errors[] = 'Your email could not be registered due to a system error. We apologize for any inconvenience.';
}
} else { // The email address is not available.
$errors[]= 'That email address has already been registered.';
}
} else { // Report the errors.
echo json_encode($errors);
} // End of if (empty($errors)) IF.
mysqli_close($dbc);
} // End of the main Submit conditional.
?>
<html>
<body>
<form action="?" method="post" id="calc" on>
<div class="calculator-submit">
<p>
<input type="text" name="full_name" size="25" maxlength="120" value="<?php if (isset($trimmed['full_name'])) echo $trimmed['full_name']; ?>" placeholder="Name"/>
<br />
<input type="email" name="email" size="25" maxlength="65" value="<?php if (isset($trimmed['email'])) echo $trimmed['email']; ?>" placeholder="Email"/>
</p>
<p>
</p>
</div>
<div class="submit-cont">
<input type="submit" name="submit" id="calc_submit" value="Submit" />
<input type="hidden" name="submitted" value="TRUE" />
</div>
</form>
<div>
<!-- END Calculator Submit Form -->
<div class="calculator-statement" style="display:none;">
<h2>Check your email</h2><br />
</div>
<script>
$(function () {
$("#calc").on('submit', function(e) {
e.preventDefault();
});
$("#calc_submit").click(function () {
$.ajax({
url: '',
data: $("#calc").serialize(),
method: 'post',
success: function(d) {
// d will hold the json representation of $errors
if (d.length) {
// there are errors
console.dir(d);// output to he console to see what they are
}
else {
// success!
$(".submit-cont").hide("slow");
$(".calculator-statement").show("slow");
}
}
});
});
});
</script>
</body>
</html>
Ray, sorry I hadn't seen your post when I submitted mine. AJAX definitely the way to go here :)
ASKER
@rob, thanks for this example. This is the way to go. Thanks to you and Ray. Two final questions from the example you sent,
1. how do I get the error messages to do a for each?
2. The error message returned is in brackets. How do I remove them? It looks like this when returned:
["You forgot to enter your name.","You forgot to enter a valid email address."]
1. how do I get the error messages to do a for each?
2. The error message returned is in brackets. How do I remove them? It looks like this when returned:
["You forgot to enter your name.","You forgot to enter a valid email address."]
$("#calc_submit").click(function () {
$.ajax({
url: 'http://jaymillerconsulting.com/ltv_email_ajax.php',
data: $("#calc").serialize(),
method: 'post',
success: function (d) {
// d will hold the json representation of $errors
if (d.length) {
// there are errors
$( "div.errors").html(function() {
var errormessage = d;
return errormessage;
});
} else {
// success!
$(".submit-cont").hide("slow");
$(".calculator-statement").show("slow");
}
}
ASKER CERTIFIED SOLUTION
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
Note that AJAX is never needed. It's purely for improving the user experience (by not reloading the page) as you could always post all the data to the server and recreate the page.
I'm inclined to agree with Slick on this after chewing on it for a bit if I'm correct in saying that the "state" of your page can be recreated easily from the PHP. By "state", I mean the logic behind why you are showing a form and what the user can or should do next and also the way the page looks because of the previous user interactions.
AJAX is useful when you want to stay on the same page and retain the visual state of that page (e.g. scroll position). This can get quite complex to do via PHP when you have a lot going on in your front end. This forms part of the methodology of Model, Views and Controllers. Separating your elements makes for easier coding, readability, SEO and performance.
With the example of a simple contact form, the user is only going to fill it out once and submit so it doesn't really make sense to use AJAX in that case.
On the other hand, take this question thread, if it didn't use AJAX and the page refreshed it wouldn't retain the simple scroll position (state) and you'd have to navigate back to where you were when you posted the comment; not a good user experience.
Another example is filling out a form and halfway through due to the user selecting say a category, you need to show them the contents of that category (from your database) then using AJAX will not affect the selections they've already made on the page. The flipside is refreshing the page gives you the opportunity to save the selections they've already made in their session.
There's a lot to consider and I would think about how important it is to separate the way your front end works from your backend. Too much front end control from PHP (controlling classes or showing/hiding elements) IMO isn't going to do you any favours.
Side note: Remember that all validation needs to happen in your PHP. Some basic parsing can happen in JavaScript but the validation MUST happen server side.
I'm inclined to agree with Slick on this after chewing on it for a bit if I'm correct in saying that the "state" of your page can be recreated easily from the PHP. By "state", I mean the logic behind why you are showing a form and what the user can or should do next and also the way the page looks because of the previous user interactions.
AJAX is useful when you want to stay on the same page and retain the visual state of that page (e.g. scroll position). This can get quite complex to do via PHP when you have a lot going on in your front end. This forms part of the methodology of Model, Views and Controllers. Separating your elements makes for easier coding, readability, SEO and performance.
With the example of a simple contact form, the user is only going to fill it out once and submit so it doesn't really make sense to use AJAX in that case.
On the other hand, take this question thread, if it didn't use AJAX and the page refreshed it wouldn't retain the simple scroll position (state) and you'd have to navigate back to where you were when you posted the comment; not a good user experience.
Another example is filling out a form and halfway through due to the user selecting say a category, you need to show them the contents of that category (from your database) then using AJAX will not affect the selections they've already made on the page. The flipside is refreshing the page gives you the opportunity to save the selections they've already made in their session.
There's a lot to consider and I would think about how important it is to separate the way your front end works from your backend. Too much front end control from PHP (controlling classes or showing/hiding elements) IMO isn't going to do you any favours.
Side note: Remember that all validation needs to happen in your PHP. Some basic parsing can happen in JavaScript but the validation MUST happen server side.
As for getting the errors, they're all in a simple array so assuming you have an element you want to show the errors:
success: function(d) {
// d will hold the json representation of $errors
if (d.length) {
// there are errors
for (err in d) {
$("#errors").append("<p class='error'>"+err+"</p>");
}
}
else {
// success!
$(".submit-cont").hide("slow");
$(".calculator-statement").show("slow");
}
}
2. The error message returned is in brackets. How do I remove them? It looks like this when returned:
["You forgot to enter your name.","You forgot to enter a valid email address."]
This looks like a JSON return - you can simply add the
dataType: "JSON"
To your AJAX request and the return in your success - should then be a javascript array.
In other words
["You forgot to enter your name.","You forgot to enter a valid email address."]
This looks like a JSON return - you can simply add the
dataType: "JSON"
To your AJAX request and the return in your success - should then be a javascript array.
In other words
$("#calc_submit").click(function () {
$.ajax({
url: 'http://jaymillerconsulting.com/ltv_email_ajax.php',
data: $("#calc").serialize(),
method: 'post',
dataType: 'JSON', /ADD THIS
success: function (d) {
// d will hold the json representation of $errors
if (d.length) {
// there are errors
$.each(d, function(index, item) {
// DO SOMETHING WITH ERROR MESSAGE HERE
});
} else {
// success!
$(".submit-cont").hide("slow");
$(".calculator-statement").show("slow");
}
}
});
});
Also take a look at the docs for JQuery .ajax . The success call back is being deprecated in favour of then
Yeah it was only showing brackets because I had you outputting it to the console. JQuery's Ajax function will automatically recognise the returned data as json so it's not needed but probably good practice as an error is thrown if json format isn't returned. The way I had it, a string, xml etc could be returned and it wouldn't throw an error. Not something you want, I suspect.
@rgranlund ? ? , you still here?
In my view, It takes time and effort to learn to Correctly use any server-browser Exchange as AJAX processes, especially for someone that is not familiar with using JavaScript and-or Jquery, it is not easy to understand, even if you just copy and paste code as you did here, and hope that the code works for you.
In my view, It takes time and effort to learn to Correctly use any server-browser Exchange as AJAX processes, especially for someone that is not familiar with using JavaScript and-or Jquery, it is not easy to understand, even if you just copy and paste code as you did here, and hope that the code works for you.
Maybe the best design would be one that has both divs in the HTML. The jQuery script could have a success function that changes the visibility. So rather than sending some JavaScript after the PHP action script has taken control of the process, you could send just a signal from the PHP action script, and the jQuery success function could change the visibility of the divs based on the information gotten from the server-side script. Just a thought.