I have a form with a button to edit an existing record. On button click, a modal opens to update the record, including a button to delete an existing file attached to the record which, when clicked triggers an ajax call to a delete_file PHP script. If a file exists, its file name is previewed in the 'p' element.
The problem I'm running into is that if the user edit's a record that didn't contain a file, uploads a file, and then deletes it without saving the record, my existing code doesn't work to delete the file. It's because HTML is dynamically being generated on file upload to place the file url in a button attribute which is not available to pass to file delete.
After researching I believe the solution is event delegation. I've tried several recommendations but none have worked. How can I:
HTML:
<div id='file_upload' class='file-upload'>
<input type='file' id='file_input' style='opacity:0;' />
<p class='file_upload_text'>Click to upload file</p>
</div>
<div id='file_upload_preview' class='file-upload file-preview' style='display:none;'>
<div class='file_preview'></div>
<button id='fileurl' data-fileurl='' class='file_delete'>Delete</button>
</div>
JQuery:
jQuery(document).ready(function($) {
var filesToUpload = [];
var fileUrlDelegated = "";
$('#file_input').on('change', function(e) {
var files = e.target.files[0];
filesToUpload.push(files);
prepareUpload(filesToUpload);
$(".file_delete").on('click', function(e) {
e.preventDefault();
$(document.body).on('change', "button [data-fileurl]", function (event) { // not working
fileUrlDelegated = $(event.target).attr("data-fileurl");
});
delete_file(fileUrlDelegated);
});
});
function prepareUpload(file) { // upload file; dynamic HTML generated after an ajax call; this works
var parent = $("#file_input").parent();
var previewID = parent.attr("id") + "_preview";
var previewParent = $("#"+previewID);
previewParent.show();
previewParent.children(".file_preview").empty().append( preview );
previewParent.children( "button" ).attr("data-fileurl", data.url );
parent.children("input").val("");
parent.hide();
}
function delete_file (file_url) { // works as long as url is provided
$(".file_preview").text("");
$("button").attr("data-fileurl", "");
$("#file_upload_preview").hide();
$("#file_upload").show();
var data = new FormData();
data.append("fileurl", file_url);
$.ajax({
url: general_globals.ajaxurl,
type: 'POST',
data: data,
processData: false,
contentType: false,
cache: false,
dataType: 'json'
});
}
You just need to rewrite your logic and rest of code
look fine to whats its doing. To delete
file and pass the data-fileurl
- You can simply check if the file URL exist at all or not which was generated by prepare Upload.
Also, to get the data attributes we can simply use .data method and write .data('fileurl')
in jQuery
to get the button fileurl
and then pass that to our delete function
for the ajax
to be call for backend
.
To get the correct fileURL
we can use $(this)
in our delete function which refer to the element we have clicked on which will be .file_delete
We will use event Delegation
in your case just to be safe since HTML are dynamically created.
Replace your delete file function to this: (Code tested on localhost and working)
//Delete file
$(document).on('click', '.file_delete', function(e) {
e.preventDefault();
//Get the file URL
var fileURL = $(this).data('fileurl')
//Check if file URL exist - then call delete else do not anything
if (fileURL != '') {
//Call delete function
delete_file(fileURL);
} else {
return false
}
});