【问题标题】:How to use JQuery event delegation on element attribute change?如何在元素属性更改上使用 JQuery 事件委托?
【发布时间】:2020-09-09 22:42:30
【问题描述】:

我有一个带有按钮的表单来编辑现有记录。单击按钮时,将打开一个模式以更新记录,包括一个用于删除附加到记录的现有文件的按钮,单击该按钮会触发对 delete_file PHP 脚本的 ajax 调用。如果文件存在,则在“p”元素中预览其文件名。

我遇到的问题是,如果用户编辑的记录不包含文件,上传文件,然后在不保存记录的情况下删除它,我现有的代码无法删除文件.这是因为 HTML 是在文件上传时动态生成的,以将文件 url 放在不可传递给文件删除的按钮属性中。

经过研究,我认为解决方案是事件委托。我已经尝试了几个建议,但都没有奏效。我该怎么做:

  1. 添加一个文件(文件名在 "$("button").attr("data-fileurl") // 这可行
  2. 单击“删除文件”按钮后,将 $("button").attr("data-fileurl") 存储在变量中
  3. 将 url 变量传递给 delete_file 函数

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'
  });
}

【问题讨论】:

    标签: php jquery ajax event-delegation


    【解决方案1】:

    您只需要重写您的逻辑,code 的其余部分就可以很好地了解它在做什么。到 delete 文件并传递 data-fileurl - 您可以简单地检查文件 URL 是否存在,这是由准备上传生成的。

    此外,要获取数据属性,我们可以简单地使用.data 方法并在jQuery 中写入.data('fileurl') 以获取按钮fileurl,然后将其传递给我们的删除function 以获取ajax请致电backend

    要获得正确 fileURL,我们可以在删除函数中使用$(this),它指的是我们点击的元素.file_delete

    为了安全起见,我们将在您的情况下使用event Delegation,因为 HTML 是动态创建的。

    将您的删除文件功能替换为:(在 localhost 上测试并运行的代码)

    //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
      }
    });
    

    【讨论】:

    • 您好,@AlwaysHelping!感谢您的回答。我会处理并报告。
    • 成功了!再次感谢您的专业知识。我接受了你的回答,因为它解决了原来的问题。然而,一个不同的问题出现了。如果一个文件存在,然后被删除,然后附加另一个文件,fileURL 保留第一个删除文件的 url,而不是第二个要删除的文件。这是一个我不会花时间解决的边缘案例,但出于好奇,这不是事件委托应该处理的吗?
    • 另外,我确认正确的 url 在 HTML 中的“data-fileurl”中。
    • @GSimmons 欢迎您提供帮助。对于第二种情况 - 我将处理的方式是我将在我的删除函数中清除删除按钮 dataURL。另外我建议使用按钮的类来分配 - 使用 .Attr 添加新文件和删除旧文件 URL - :)
    • 如果我理解正确,我相信我已经这样做了。在删除功能中,我使用 $("button").attr("data-fileurl", "") 并且它有效。在上传功能中,我使用 previewParent.children("button").attr("data-fileurl", data.url)。这两个都按预期工作。因此,当请求删除第二个文件时,HTML 中的“data-fileurl”不同于控制台记录的来自 $(this) 的 fileURL,后者是第一个删除的文件。
    【解决方案2】:

    尝试使用 FileReader API 而不是依赖 AJAX 调用。您可以制作一个类似的方法

    function readURL() {
      var input = grab your input here;
      if (input.files && input.files[0]) {
        var reader = new FileReader();
        reader.onload = function(e) {
          $('#preview').attr('src', e.target.result);
         }
         reader.readAsDataURL(input.files[0]);
       }
    };
    

    这样,在用户保存记录之前,您不会接触数据库,这样您的问题就解决了。

    【讨论】:

    • 感谢您的回复。我刚刚阅读了 FileReader。我认为这不是解决我问题的正确方法。我的代码按预期上传文件并将自定义 url 存储在“button data-fileurl”中;例如,按钮 data-fileurl="example.com/x/filename.png"。我的问题是我需要这个确切的 url 来传递给 delete_file 函数。但是,该 url 在文档准备就绪时不存在,因为文件随后上传,我无法弄清楚如何获取页面加载后动态生成的 data-fileurl。
    • 好的,在重新阅读您的答案后,我知道您将如何处理这个问题。我不想重新编写一堆已经工作的代码,但也许我可以在保存记录后重新安排代码上传文件。
    猜你喜欢
    • 1970-01-01
    • 2012-08-15
    • 1970-01-01
    • 2012-06-19
    • 1970-01-01
    • 1970-01-01
    • 2018-12-27
    • 2018-03-29
    • 1970-01-01
    相关资源
    最近更新 更多