代码之家  ›  专栏  ›  技术社区  ›  pjk_ok

移动图像预览包装时文件上载表单不起作用

  •  0
  • pjk_ok  · 技术社区  · 3 年前

    我有一个文件上传器,可以处理多个文件,这些文件都按预期工作。

    要上传的文件的预览放在上传表单的容器内。当我将此元素移动到表单的不同部分(或表单外)时,上传器不工作?理想情况下,我希望保存图像的预览容器位于提交按钮下方(表单内部或外部)。

    我一辈子都搞不清楚为什么会发生这种事。在图像预览填充元素之前,元素本身是空的,我不认为问题是由javascript引起的(尽管很乐意接受这方面的指导)。

    有问题的要素是:

    <div id="show-selected-images"></div>
    

    它目前位于表单的中间,位于放置区域和(隐藏的)文件输入元素以及一个可见的提交按钮之间,但如上所述,我想将其移动到提交按钮下方。

    注意: 我已经包含了JS,所以上传器可以工作,但我怀疑JS可能不是问题所在。

    代码笔: https://codepen.io/pauljohnknight/pen/xxdrvmR

    // Query all needed elements in one go
    const [dropZone, showSelectedImages, fileUploader] = document.querySelectorAll(
      "#standard-upload-files, #drop-zone, #show-selected-images"
    );
    
    dropZone.addEventListener("click", (evt) => {
      // assigns the dropzone to the hidden input element so when you click 'select files' it brings up a file picker window
      fileUploader.click();
    });
    
    // Prevent browser default when draging over
    dropZone.addEventListener("dragover", (evt) => {
      evt.preventDefault();
    });
    
    fileUploader.addEventListener("change", (evt) => {
      // Clear the already selected images
      showSelectedImages.innerHTML = "";
      // this function is further down but declared here and shows a thumbnail of the image
      [...fileUploader.files].forEach(updateThumbnail);
    });
    
    dropZone.addEventListener("drop", (evt) => {
      evt.preventDefault();
      // Clear the already selected images
      showSelectedImages.innerHTML = "";
    
      // assign dropped files to the hidden input element
      if (evt.dataTransfer.files.length) {
        fileUploader.files = evt.dataTransfer.files;
      }
    
      // function is declared here but written further down
      [...evt.dataTransfer.files].forEach(updateThumbnail);
    });
    
    // updateThumbnail function that needs to be able to handle multiple files
    function updateThumbnail(file) {
      if (file.type.startsWith("image/")) {
        const thumbnailElement = new Image();
        thumbnailElement.classList.add("drop-zone__thumb");
        thumbnailElement.src = URL.createObjectURL(file);
        showSelectedImages.append(thumbnailElement);
      }
    } // end of 'updateThumbnail' function
    body {
      margin: 0;
      display: flex;
      justify-content: center;
      width: 100%;
    }
    
    form {
      width: 30%;
    }
    
    #drop-zone {
      border: 1px dashed;
      width: 100%;
      padding: 1rem;
      margin-bottom: 1rem;
    }
    
    .select-files {
      text-decoration: underline;
      cursor: pointer;
    }
    
    /* image that is previewed prior to form submission*/
    .drop-zone__thumb {
      width: 200px;
      height: auto;
      display: block;
    }
    
    #submit-images {
      margin-top: 1rem;
    }
    <form id="upload-images-form" enctype="multipart/form-data" method="post">
      <h1>Upload Your Images</h1>
      <div id="drop-zone" class="drop-zone">
        <p class="td text-center">DRAG AND DROP IMAGES HERE</p>
        <p>Or</p>
        <p class="select-files">Select Files</p>
      </div>
      <!-- below is the element that has the issue when moved -->
      <div id="show-selected-images"></div>
      <div class="inner-input-wrapper">
        <div class="upload-label-wrapper">
          <input id="standard-upload-files" style="display:none" type="file" name="standard-upload-files[]" multiple>
        </div>
        <input type="submit" name="submit-images" id="submit-images" value="SUBMIT IMAGES">
      </div>
    </form>
    1 回复  |  直到 3 年前
        1
  •  1
  •   Danila    3 年前

    我认为这部分导致了这个问题:

    // Query all needed elements in one go
    const [dropZone, showSelectedImages, fileUploader] = document.querySelectorAll(
      "#standard-upload-files, #drop-zone, #show-selected-images"
    );
    

    这样查询元素是非常糟糕的做法,因为如果不更改解构数组中的元素,就无法更改它们在html中的顺序。在您的情况下,您最终正在移动预览,现在您的 showSelectedImages 变量实际上是上传器,并且 fileUploader 现在是保存预览的div,一切都一团糟。

    您需要逐一查询:

    const fileUploader = document.getElementById('standard-upload-files');
    const dropZone = document.getElementById('drop-zone');
    const showSelectedImages = document.getElementById('show-selected-images');