I'm building a support contact form where the user can upload files. The file upload is managed using AJAX: the user can upload the files, then submit the form at their convenience. The current layout that works is, however, not aesthetic: the upload input is below the form submit button.
I read about nested forms and the new form
attribute and I thought this would do the trick:
<form action="" method="post" enctype="multipart/form-data" id="main-form">
...
<form action="/upload_file_ajax.php" method="post" id="file-upload-form">
<div class="form-group row mb-3 mb-3">
<label class="col-sm-3 col-lg-3 col-form-label" for="file"><?php echo $label['attach-file']; ?></label>
<div class="col-sm-8 col-lg-7">
<input class="form-control custom-file-input" name="file" id="file" type="file" form="file-upload-form" />
</div>
</div>
</form>
<div class="form-group row">
<div class="col-4 offset-3">
<button type="submit" name="submit" class="btn btn-outline-success" form="main-form"><?php echo $label['submit-button']; ?></button>
</div>
</div>
</form>
I have added the form
attribute to every input and button. However, the inner form ("file-upload-form") won't submit at all when I add the file.
Could it be because this is an auto-submit input, i.e. the Javascript triggers the AJAX when the file is selected? This is the trigger line:
$('#file-upload-form').on('change', function(e){
...
As soon as I move the nested form below the closing </form>
tag of the main form, it works.
If the aesthetic layout can be achieved in any other way, e.g. the file upload input can appear above the Submit button without nesting the forms, please let me know.
EDIT: This is the revised Javascript that takes care of the file upload via AJAX. I have removed the inner form
tags as advised but the input still won't submit.
$(function(){
// listen for input changes (when a file is selected)
$('#file-upload-input').on('change', function(e){
//var formData = new FormData();
// file has been selected, submit it via ajax
$.ajax({
type: 'POST',
url: "/upload_file_ajax.php",
data: new FormData(this),
cache: false,
contentType: false,
processData: false,
success: function(data){
// the upload_file_ajax.php endpoint returns the file name and a status message for the uploaded file
console.log(data.filename, data.message);
// we then inject these into the main data form
var $hiddenInput = $('<input type="hidden" name="uploads[]" value="'+data.filename+'">');
$('#main-form').append($hiddenInput);
// show a thumbnail maybe?
var $thumbnail = $('<img src="/uploaded_files/'+data.filename+'" width="40" height="40" />');
$("#preview").append($thumbnail);
$("#status").html(JSON.stringify(data.message));
// reactivate file upload form to choose another file
$('#file-upload-input').val('');
},
error: function(){
console.log("error");
}
});
});
});
This is what the revised HTML looks like:
<form action="" method="post" enctype="multipart/form-data" id="main-form">
... (other inputs here)...
<div class="form-group row offset-3 mb-3">
<div class="col-12" id="preview"></div>
<div class="col-12" id="status"></div>
</div>
<div class="form-group row mb-3 mb-3">
<label class="col-sm-3 col-lg-3 col-form-label" for="file"><?php echo $label['attach-file']; ?></label>
<div class="col-sm-8 col-lg-7">
<input class="form-control custom-file-input" name="file" id="file" type="file" id="file-upload-input" form="file-upload-form" />
</div>
</div>
<div class="form-group row">
<div class="col-4 offset-3">
<button type="submit" name="submit" class="btn btn-outline-success" form="main-form"><?php echo $label['submit-button']; ?></button>
</div>
</div>
</form>