问题
So I have verified that my contact.php
(phpmailer file) is working. However at the end, given a successful response, the contact.php
says echo: 'done'
if(!$mail1->send()) {
echo 'error';
//echo 'Mailer Error: ' . $mail->ErrorInfo;
return false;
} else {
echo 'done';
return true;
}
At that point (I'm guessing since I paid a developer to create the form for me, but haven't tried to test with my own host til recently. This is the code he supplied.
/************
AJAX Method
*************/
function submitForm()
{
//1. user clicked on submit/send button after filling form
$('#contactform').on('submit',function(e){
//2. this line will prevent the window's reload!
e.preventDefault();
});//end form submit
//3. handilg the success div
$('#success_message').show();
$('#success_message h2').text('Processing, wait please...');
$('#submit_cf').attr('disabled','disabled');
//4. the actual ajx process starting from here
$formData = $('#contactform').serialize();
$.ajax({
url : "contact.php",
type: "POST",
data : $formData,
success: function(data) {
//data - response from server
//console.log(data);
if(data == 'done'){
$('#success_message h2').text('Mail Sent Successfully!');
}else{
$('#success_message h2').text('There is an error, try again later!');
// $('#submit_cf').attr('disabled','disabled');
}
}//end success
});//end ajax
}//end submitForm() function
})(jQuery, window, document);
</script>
I'm assuming that echo: 'data'
, return: true
shoud send the word data
back to the ajax form where the:
if(data == 'done'){
$('#success_message h2').text('Mail Sent Successfully!');
would take over and populate the div#success_message h2
html with Mail Sent Successfully
.
Only instead, the ajax doesn't work at all. Instead a new page loads with just the word "done" on it (which is what I expect happens when you use echo:'done').
I don't know how to make ajax take in 'done' and then populate the same page with the success message.
I loaded jquery into the header, as it is used for several other scripts. The ajax script is in the html rather than an external script.
Please tell there is a simple fix, or do I need to start over with Swift?
回答1:
After looking at the script, it's set up kind of strange. I will notate what I think you need to change but first answer your questions:
I'm assuming that echo: 'data', return: true should send the word data back to the ajax form...
No, data
is what is being returned from the ajax page, in my answer I have changed it to say response
so it is clearer what it does. It will contain the success/error message
Instead a new page loads with just the word "done" on it...
This usually indicates that there is an issue, either jQuery is not loaded first or there is an error that stops the jquery running properly, so the line that is supposed to stop the form from submitting normally (e.preventDefault()
) is interrupted.
I loaded jquery into the header, as it is used for several other scripts. The ajax script is in the html rather than an external script.
This shouldn't be too hard to remedy, you can have this script on it's own instead of the html. It has to be between the event listener instead of the way your's has it and make sure it is placed after the jQuery library loads:
<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script type="text/javascript" src="/js/myScript.js"></script>
Please tell there is a simple fix, or do I need to start over with Swift?
You should not have to start over in Swift
/js/myScript.js
$(document).ready(function(){
// Make a function on this would make more sense, but you only need it if you
// want to re-use this feature, otherwise you can incorporate it back
// I made it as a function so it cleans up the submit a bit
function doSuccess(acton,message,disable)
{
$(acton).show();
$(acton+' h2').text(message);
$(disable).attr('disabled','disabled');
}
// It's strange to have the on('submit') inside the function since it's
// a listener, you shouldn't need to wrap this in a function, but wrap
// everything inside the listener instead
$('#contactform').on('submit',function(e){
// This is fine, it does prevent the form from submitting
e.preventDefault();
// Assign to variable this form
var thisForm = $(this);
// Run messaging
doSuccess('#success_message','Processing, please wait...','#submit_cf');
// Run ajax
$.ajax({
url : "contact.php",
type: "POST",
// You can serialize the form here
data : thisForm.serialize(),
success: function(response) {
// Just do the text here from php
$('#success_message h2').text(response);
}
});
});
});
On the PHP side, just echo the message. Make it easier since you don't have any complex return:
# You can use a ternary since there are only two options
echo ($mail1->send())? 'Your message sent successfully' : 'There is an error, try again later!';
# Unless there is a reason to return true or false (unless this is part of a
# function or method), you don't need it. It's not doing anything
One last note, where ever you are using the submitForm()
(likely it's on your submit button or something as an inline javascript), you should be able to just remove that since the function won't exist anymore.
EDIT/JUST AS A SIDE: I am just going to demonstrate how I do this (in as simple example as I can) in order to get consistent results over and over. It may be too complex for you at this stage but, if you are interested and read the notations it's pretty straight forward. If you copy everything and put them in the correct folders as I labelled below, you can see it work first before you decide to implement it.
It involves a dispatcher page, an xml page, and a javascript ajax object. The idea is that you can build it out and do automated workflows using xml as the automation instructions:
/dispatcher.php
This is the page that will receive your ajax calls. It would receive ALL ajax calls and dispatch the correct instructions. You would want to build some checks (like form token matches) into it because this kind of automation can be dangerous. These are the basics of it:
// Check specifically for actions
if(!empty($_POST['action'])) {
// This will fetch an xml file and parse it (see next section)
$config = simplexml_load_file(__DIR__."/xml/settings.xml");
// Assign the action
$action = $_POST['action'];
// Check the parsed file for the proper ajax action
if(!empty($config->ajax->action->{$action})) {
// Loop through the action
foreach($config->ajax->action->{$action} as $do) {
// If there is an include action
if(isset($do->{"include"})) {
// Loop through the includes
foreach($do->{"include"} as $include) {
// If the file exists, include it
if(is_file($inc = __DIR__.$include))
include($inc);
}
}
}
}
// Stop processing
exit;
}
/xml/settings.xml
This is just a basic xml file to help automate your calls. It's pretty straight forward. One thing to note, you will want to put the xml folder outside the root OR use a .htaccess
(or web.config
for Windows) to secure this folder from access except php. There are examples on the web of this. You can expand this xml out to include multiple pages with the <include>
tag and the dispatcher will run one after the other.
<?xml version="1.0" encoding="UTF-8"?>
<config>
<ajax>
<action>
<!-- This would correlate to a hidden field in your form. See html form example -->
<email_user>
<include>/contact.php</include>
<!-- To run more actions on this call, just add another tag here -->
<!-- <include>/another/page/here.php</include> -->
</email_user>
</action>
</ajax>
</config>
/js/myScript.js
This is slightly different that the above version. I would use an Ajax object so it can be re-used.
// @param $ [object] This accepts jQuery object
var AjaxEngine = function($)
{
// Used to overwrite default url
var useUrl;
// Default url for call
var url = '/dispatcher.php';
// This is the do before function
var beforeFunc;
// This is the default do before
var useBefore = false;
// This is what overwrites the url (not needed in this instance)
this.useUrl = function(useUrl)
{
url = useUrl;
return this;
}
// This assigns the beforeSend action in ajax
this.doBefore = function(beforeFunc)
{
useBefore = beforeFunc;
return this;
}
// This is the actual send function
// @param data [object] This is what data to send to the dispatcher
// @param fun [object] This is the anonymous function that will run
// on success of the form
this.send = function(data,func)
{
$.ajax({
// Runs before the sending (this is where you add waiting messages)
beforeSend: useBefore,
url: url,
data: data,
type: 'post',
// This will take the response and drop it into the
// anonymous function
success: function(response){
func(response);
}
});
return this;
};
}
// Wait for document to be ready
$(document).ready(function(){
// If you use a class, you can act on any form that has the "ajax_form" class
// This is very powerful. It means you can have many different forms on
// the same page and use the same script/dispatcher to run/process each
$('.ajax_form').on('submit',function(e){
e.preventDefault();
var thisForm = $(this);
// Create new ajax engine, you have to pass jQuery for ajax to work
var Ajax = new AjaxEngine($);
// Set do before action, in your case you have 3 things that must
// happen before ajax sends. In this example, this function is fixed
// (not ideal), but you can add automation so you send the correct
// doBefore function on a per-form basis
Ajax.doBefore(function() {
$('#success_message').show();
$('#success_message h2').text('Processing, please wait...');
$('#submit_cf').attr('disabled','disabled');
})
// Send the form data and response function to "/dispatcher.php"
.send(thisForm.serialize(),function(response) {
// Do a "try/catch" here, that way you can catch errors
// Most common in this scenario would be an empty response, or
// mal-formed json (like a fatal error in php or whatever)
try {
// Parse the response
var parseResp = JSON.parse(response);
// See if there are instructions
var instr = (parseResp.instructions !== "undefined")? parseResp.instructions : 'text';
// Apply instructions, these are just some examples.
switch(instr) {
case('html'):
// Take from php apply html
$(parseResp.sendto).html(parseResp.data);
break;
default:
// Take from php apply text
$(parseResp.sendto).text(parseResp.data);
}
}
catch(Exception) {
// This will show you in the console what is wrong
console.log(Exception.message);
// This will show you what was received back so you can address issue
console.log(response);
}
});
});
});
/index.php
Example form in the root of the site:
<form action="/tester.php" id="contactform" class="ajax_form">
<div id="success_message">
<h2>Hey</h2>
</div>
<input type="text" name="test" value="1050724273" />
<!-- Send this to the dispatcher and match the value in the xml file -->
<input type="hidden" name="action" value="email_user" />
<input type="submit" value="Save" />
</form>
/contact.php
Finally, this is the page that will be run in our automation based on the tag in the xml file. Key to this is to return json:
<?php
// Do all your code first, then output json at the very bottom
// For complex html output, do a buffer so you can capture it easily
ob_start();
?>
<h1>Hello people</h1>
<?php
// Get the above text/html from the buffer
$data = ob_get_contents();
// Clear out the buffer
ob_end_clean();
// This is what will be sent back as the "response" in the ajax
$response = array(
// This will tell the ajax where to drop the response
'sendto'=>'#contactform',//'#success_message h2',
// This is the content from above (<h1>Hello people</h1>)
'data'=>$data,
// This is just incase you want to expand out the ajax
// to include checks for success and failure
'success'=>true,
// This tells your ajax how to output using the switch
'instructions'=>'html'//'text'
);
// If you have extra includes that you want to run in the ajax call,
// don't die here, but in this instance, since there is only one include (contact.php),
// just die and output the response
die(json_encode($response));
来源:https://stackoverflow.com/questions/39060278/success-message-not-displaying-using-jquery-ajax