Products
GG网络技术分享 2025-03-18 16:12 4
I am trying to create form and submitting this with ajax. So the page wont reload. I don\'t have a lot of experience with ajax and I am trying to find as much information as I can.
Right now in my code I can sbmit form without reloading. But I have a field for uploading files. I know It is a bit different to do this and I also found some examples but so far no luck. For example Ajax file upload in Wordpress - can\'t pass FormData
Right now I have My Ajax code like this:
Ajax
(function($) {jQuery(document).ready(function() {
// when user submits the form
jQuery(document).on(\'submit\', \'.form-assignment\', function(event) {
var error_elm = jQuery(\'.ajax-error\');
var response_elm = jQuery(\'.ajax-response\')
// var widgetId = grecaptcha.reset(container);
error_elm.html(\'\');
response_elm.html(\'\');
// prevent form submission
event.preventDefault();
var form_elm = jQuery(this);
var url = form_elm.data(\'url\');
var action = form_elm.data(\'action\');
var form_data = new FormData();
var data = {
action: action,
form_data : form_data
};
// add loading message
response_elm.html(\'Loading...\');
jQuery.ajax({
type : \'POST\',
url : url,
data : data,
processData: false,
contentType: false,
enctype: \'multipart/form-data\',
dataType : \'json\',
async : true
}).success(function(response) {
error_elm.html(\'\');
response_elm.html(\'\');
if(response.status !== \'success\') {
// something went wrong
if(response.message) {
error_elm.html(response.message);
return;
}
// don\'t know ?
}
// success!!
// log data
console.log(response);
// display data
response_elm.html(response.message);
$(\"#form-assignment\").trigger(\"reset\");
grecaptcha.reset();
}).error(function(response) {
error_elm.html(\'\');
response_elm.html(\'\');
error_elm.html(response.statusText);
});
});
});
})( jQuery );
My form:
<div class=\"ajax-error\" style=\"color: red;\"></div><form class=\"form-assignment\" name=\"form_assignment\" id=\"form-assignment\"
method=\"post\" enctype=\"multipart/form-data\"
data-url=\"<?php echo esc_url( admin_url( \'admin-ajax.php\' ) ) ?>\" data-action=\"form_submit1\">
<label>name:</label>
<input type=\"text\" name=\"customer-field-text\"pattern=\"[a-zA-Z0-9 ]+\" placeholder=\"<?php echo $field->label ?>\" size=\"40\"/>
<label>file upload</label>
<input type=\"file\" name=\"customer-field-upload\" id=\"customer-field-upload\"
multiple=\"false\"/>
</form>
Right now this is how far I got. This is not my full form I have already added nonce and other required settings for sequrity. When I check input file It keep displaying error message that the field is empty.
My form handler
function handle_form_submission (){global $wpdb;
$response = array(
\'status\' => \'error\',
\'message\' => \'\',
);
parse_str($_POST[\'form_data\'], $form_data);
//global $error;
$error = new WP_Error();
if (empty($_POST[\'customer-field-name\']) ) {
$error->add(\'empty\',\'Name is required.\');
}
if (empty($_POST[\'customer-field-upload\']) && empty($_FILES[\"customer-field-upload\"][\"name\"])) {
$error->add(\'empty\',\'select an file.\');
}
if ( !empty( $error->get_error_codes() ) ) {
$error_messages = $error->get_error_messages();
$error = \'\';
foreach($error_messages as $error_message) {
$error .= \'<p>\'.$error_message.\'</p>\';
}
$response[\'message\'] = $error;
wp_send_json( $response );
wp_die();
}
$name = sanitize_text_field( $form_data[\"customer-field-name\"] );
$upload = sanitize_text_field( $form_data[\"customer-field-upload\"] );
require_once( ABSPATH . \'wp-admin/includes/image.php\' );
require_once( ABSPATH . \'wp-admin/includes/file.php\' );
require_once( ABSPATH . \'wp-admin/includes/media.php\' );
media_handle_upload( \'customer_field_upload\', $form_data[\'post_id\'] );
}
add_action( \'wp_ajax_form_submit1\', \'handle_form_submission\' );
// ajax hook for non-logged-in users: wp_ajax_nopriv_{action}
add_action( \'wp_ajax_nopriv_form_submit1\', \'handle_form_submission\' );
So My question is What can I do or add in my ajax or form handler to get file upload submit with Ajax working. Any suggestion, advice or some existing example that are familiar will be appreciated. I am practicing with WordPress and Ajax that is how far I got.
I have tried to use FormData but still no luck so far.
Here is some tips to make work your provided form:
Form:
<div class=\\\"ajax-error\\\" style=\\\"color: red;\\\"></div><form class=\\\"form-assignment\\\" name=\\\"form_assignment\\\" id=\\\"form-assignment\\\" method=\\\"post\\\" enctype=\\\"multipart/form-data\\\"
data-url=\\\"<?php echo esc_url(admin_url(\'admin-ajax.php\')) ?>\\\" data-action=\\\"form_submit1\\\">
<label>name:</label>
<input type=\\\"text\\\" name=\\\"customer-field-text\\\" pattern=\\\"[a-zA-Z0-9 ]+\\\" size=\\\"40\\\"/>
<label>file upload</label>
<input type=\\\"file\\\" name=\\\"customer-field-upload\\\" id=\\\"customer-field-upload\\\" multiple=\\\"false\\\"/>
<input type=\\\"submit\\\" value=\\\"Submit\\\" name=\\\"submit\\\">
</form>
I removed placeholder=\\\"<?php echo $field->label ?>\\\"
from your text
input, because it\'s coming from custom code, which you didn\'t provide.
Ajax.js:
jQuery(document).ready(function ($) {// when user submits the form
jQuery(document).on(\'submit\', \'.form-assignment\', function (event) {
var error_elm = jQuery(\'.ajax-error\');
var response_elm = jQuery(\'.ajax-response\');
error_elm.html(\'\');
response_elm.html(\'\');
event.preventDefault();
var form_elm = jQuery(this);
var url = form_elm.data(\'url\');
var action = form_elm.data(\'action\');
var file = form_elm[0][1].files[0];
var customer_field_text = form_elm[0][0].value;
var form_data = new FormData();
form_data.append(\'action\', action);
form_data.append(\'customer-field-upload\', file);
form_data.append(\'customer-field-name\', customer_field_text);
response_elm.html(\'Loading...\');
jQuery.ajax({
type: \'POST\',
url: url,
data: form_data,
processData: false,
contentType: false,
cache: false
}).success(function (response) {
error_elm.html(\'\');
response_elm.html(\'\');
if (response.status !== \'success\') {
// something went wrong
if (response.message) {
error_elm.html(response.message);
return;
}
// don\'t know ?
}
response_elm.html(response.message);
$(\\\"#form-assignment\\\").trigger(\\\"reset\\\");
}).error(function (response) {
error_elm.html(\'\');
response_elm.html(\'\');
error_elm.html(response.statusText);
});
});
});
NOTE: You\'re using var form_elm = jQuery(this);
, which returns object of jquery with all Form content. That\'s why I used it for accessing input information. Instead you can access to form inputs with their name, class, id, placeholder and etc.
What changed:
(function($) {}
wrapper and instead used jQuery(document).ready(function ($) {});
. This is just for note. There is no need to wrapp your jquery to have access to $
.We\'re getting file and name from inputs with lines below:
var file = form_elm[0][1].files[0];var customer_field_text = form_elm[0][0].value;
We\'re adding action
for WordPress and form inputs with their values into FormData
:
form_data.append(\'action\', action);form_data.append(\'customer-field-upload\', file);
form_data.append(\'customer-field-name\', customer_field_text);
Here you can change the name of array we\'re sending. For ex., we will recieve file in the array with key customer-field-upload
and can use it such way:
$_FILES[\'customer-field-upload\']
async : true
: this line we don\'t need. It\'s true by default. enctype: \'multipart/form-data\',
we don\'t need, too.data: form_data,
: we are sending everything only using one form_data
variable( FormData
object ).PHP file:
add_action(\'wp_ajax_nopriv_form_submit1\', \'handle_form_submission\');
because there is nothing related to nonce
in your provided codeYour $_POST
will contain:
Array(
[action] => form_submit1 //action, which we used to send and accept Ajax request
[customer-field-name] => some input value in the name field
)
You can access to name input using $_POST[\'customer-field-name\']
.
Your $_FILES
will contain:
Array(
[customer-field-upload] => Array
(
[name] => input file name
[type] => input file type
[tmp_name] => temp file
[error] => 0
[size] => some size
)
)
You can work with input file using $_FILES[\'customer-field-upload\']
EDIT: Appended functional to add all inputs with several lines of code:
Form:
<div class=\\\"ajax-error\\\" style=\\\"color: red;\\\"></div><form class=\\\"form-assignment\\\" name=\\\"form_assignment\\\" id=\\\"form-assignment\\\" method=\\\"post\\\" enctype=\\\"multipart/form-data\\\"
data-url=\\\"<?php echo esc_url(admin_url(\'admin-ajax.php\')) ?>\\\" data-action=\\\"form_submit1\\\">
<label for=\\\"customer-field-text\\\">name:</label>
<input type=\\\"text\\\" name=\\\"customer-field-text\\\" id=\\\"customer-field-text\\\" pattern=\\\"[a-zA-Z0-9 ]+\\\" size=\\\"40\\\"/>
<label>file upload</label>
<input type=\\\"file\\\" name=\\\"customer-field-upload\\\" id=\\\"customer-field-upload\\\" multiple=\\\"false\\\"/>
<label for=\\\"select\\\">select:</label>
<select name=\\\"carlist\\\" id=\\\"select\\\">
<option value=\\\"1\\\">1</option>
<option value=\\\"2\\\">2</option>
<option value=\\\"3\\\">3</option>
<option value=\\\"4\\\">4</option>
</select>
<label for=\\\"email\\\">email: </label>
<input type=\\\"text\\\" name=\\\"email\\\" id=\\\"email\\\">
<input type=\\\"submit\\\" value=\\\"Submit\\\" name=\\\"submit\\\">
</form>
Ajax.js:
jQuery(document).ready(function ($) {// when user submits the form
jQuery(document).on(\'submit\', \'.form-assignment\', function (event) {
var error_elm = jQuery(\'.ajax-error\');
var response_elm = jQuery(\'.ajax-response\');
error_elm.html(\'\');
response_elm.html(\'\');
event.preventDefault();
var form_elm = jQuery(this);
var url = form_elm.data(\'url\');
var action = form_elm.data(\'action\');
var file_input_name = jQuery(\'#form-assignment\').find(\'input[type=file]\').attr(\'id\');
var form_data = new FormData();
form_data.append(\'action\', action);
jQuery.each(jQuery(\':input:not([type=submit]):not([type=file])\', \'#form-assignment\' ), function(i, fileds){
form_data.append(jQuery(fileds).attr(\'name\'), jQuery(fileds).val());
});
jQuery.each(jQuery(\':input:not([type=submit]):not([type=text]):not([type=select])\', \'#form-assignment\' )[0].files, function(i, file){
form_data.append(file_input_name, file);
});
response_elm.html(\'Loading...\');
jQuery.ajax({
type: \'POST\',
url: url,
data: form_data,
processData: false,
contentType: false,
cache: false
}).success(function (response) {
error_elm.html(\'\');
response_elm.html(\'\');
if (response.status !== \'success\') {
// something went wrong
if (response.message) {
error_elm.html(response.message);
return;
}
// don\'t know ?
}
response_elm.html(response.message);
$(\\\"#form-assignment\\\").trigger(\\\"reset\\\");
}).error(function (response) {
error_elm.html(\'\');
response_elm.html(\'\');
error_elm.html(response.statusText);
});
});
});
Here we used Jquery iterator to add several values from the loop into the FormData
object. This is example and can be applied for checkboxes, textareas and etc.
###
You are missing enctype: \'multipart/form-data\'
and contentType: false
to prevent jQuery from setting it to string. If that doesn\'t work, see this example and follow the same method
jQuery.ajax({type : \'POST\',
enctype: \'multipart/form-data\',
url : url,
data : data,
async : true,
processData: false,
contentType: false,
})
###
Your Jquery is missing the
enctype: \'multipart/form-data\'
This is quite important when you are submitting the forms. This allows the form data to be sent without any conversions.
jQuery.ajax({type : \'POST\',
url : url,
data : data,
enctype: \'multipart/form-data\',
dataType : \'json\',
async : true
}).success(function(response) {
error_elm.html(\'\');
response_elm.html(\'\');
if(response.status !== \'success\') {
// something went wrong
if(response.message) {
error_elm.html(response.message);
return;
}
// don\'t know ?
}
// success!!
// log data
console.log(response);
// display data
response_elm.html(response.message);
}).error(function(response) {
error_elm.html(\'\');
response_elm.html(\'\');
error_elm.html(response.statusText);
});
});
Demand feedback