I'm encountering the error "Illegal invocation" when attempting to use the shorthand syntax for sending form data with a file upload in an AJAX request using jQuery. However, the error disappears when I use the longer .ajax() method. I'm using CodeIgniter as the server-side framework.
What's the reason for the error with the shorthand syntax, and why does the .ajax() method work?
form
<form id="add_category_form" action="<?= base_url("CategoriesController/process_add_category") ?>" method="post" enctype="multipart/form-data">
<input type="hidden" name="<?= $this->security->get_csrf_token_name() ?>" value="<?= $this->security->get_csrf_hash() ?>" />
<h2>Add a Category</h2>
<ul>
<li>
<input type="text" name="name" required>
<label>Category Name</label>
</li>
<li>
<textarea name="description" required></textarea>
<label>Description</label>
</li>
<label>Upload Images (5 Max)</label>
<input type="file" name="image" id="category_image" accept="image/*">
</ul>
<!-- FIXME: center the content of this last li tag -->
<button type="button" data-dismiss="modal" aria-label="Close">Cancel</button>
<button type="submit">Save</button>
</form>
Using $.post
$(document).ready(function() {
$("#add_category_form").submit(function(e) {
e.preventDefault();
let url = $(this).attr("action");
if ($("#category_image").val() == "") {
alert("Please add an image");
} else {
let formData = new FormData(this); // Pass the form element
$.post(url, formData, function(response) {
console.log(response);
csrfName = response.csrfName;
$("input[name='<?= $this->security->get_csrf_token_name() ?>']").val(response.newCsrfToken);
}, "json");
}
return false;
using $.ajax
$(document).ready(function() {
$("#add_category_form").submit(function(e) {
e.preventDefault();
if ($("#category_image").val() == "") {
alert("Please add an image");
}
let formData = new FormData(this);
$.ajax({
url: "<?= base_url(''); ?>CategoriesController/process_add_category",
type: "POST",
data: formData,
processData: false,
contentType: false,
dataType: "json",
success: function(response) {
console.log(response);
csrfName = response.csrfName;
$("input[name='<?= $this->security->get_csrf_token_name() ?>']").val(response.newCsrfToken);
},
error: function(xhr, status, error) {
console.error("AJAX Error:", status, error);
}
});
return false;
});
});
You can't use a FormData
object for the data when using the shorthand version of $.post()
. The documentation says that the second argument must be either a plain object or a string, not FormData
.
You need to use a settings object just like $.ajax()
so you can specify processData: false
. Without this option, it tries to convert the object to a URL-encoded string.