Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Inquisitive's avatar

Js while removing single file from file input list, removing all files in the list

https://ibb.co/0sSKrjX

Here, as soon as i click on one of the remove button, the input filed showing, "No file choosen"

My code:

HTML

<div class="kt-form__control ks-file-uploader-container">
  <input type="file" name="uploads[kmz][]" class="ks-file-uploader" id="kmz-file" multiple>
  <div id="ks-file-uploader-preview-box"></div>
</div>

JS:

document.getElementById('kmz-file').addEventListener('change', function(evt) {
          ksHandleFileSelect(evt, document.getElementById('ks-file-uploader-preview-box'), this);
      });

      function ksHandleFileSelect(evt, selectedFiles, fileInput) {


          selectedFiles.innerHTML = '';

          let files = evt.target.files;

          for (let i = 0; i < files.length; i++) {
              let file = files[i];

              // Create a new div to hold the file name and remove button
              let fileDiv = document.createElement('div');
              fileDiv.classList.add('file');
              selectedFiles.appendChild(fileDiv);

              // Create a new span to display the file name
              let fileNameSpan = document.createElement('span');
              fileNameSpan.textContent = file.name;
              fileDiv.appendChild(fileNameSpan);

              // Create a new button to remove the file
              let removeButton = document.createElement('button');
              removeButton.textContent = 'Remove';
              removeButton.dataset.fileIndex = i;
              removeButton.dataset.fileInputId = fileInput.id;
              removeButton.addEventListener('click', ksHandleRemoveFile);
              fileDiv.appendChild(removeButton);
          }
      }

      function ksHandleRemoveFile(evt) {
          evt.preventDefault();
          evt.stopPropagation();

          let fileIndex = evt.target.dataset.fileIndex;
          let fileInputId = evt.target.dataset.fileInputId;
          let fileInput = document.getElementById(fileInputId);
          fileInput.value = '';

          let parentNode = evt.target.parentNode.parentNode;
            if(parentNode){
                let files = evt.target.parentNode.parentNode.querySelectorAll('.file');

                console.log('files', files);
                console.log('row', fileIndex, fileInputId);


                for (let i = 0; i < files.length; i++) {
                    if (i == fileIndex) {

                        console.log('equals', files[i].parentNode);
												
                        //this is where i am trying to delete only single files
                        files[i].parentNode.removeChild(files[i]);
                    } else {
                        console.log('equals not', files[i]);
                        let removeButton = files[i].querySelector('button');
                        console.log('removeButton', removeButton);
                        removeButton.dataset.fileIndex = i - (i > fileIndex ? 1 : 0);
                    }
                }
            }

      }

JS FIDDLE: https://jsfiddle.net/ju46r7s5/

0 likes
2 replies
LaryAI's avatar
LaryAI
AI
Best Answer
Level 58

The issue is that when a file is removed, the entire input field is being cleared. To remove only the selected file, the following changes can be made to the ksHandleRemoveFile function:

  1. Instead of setting fileInput.value = '', remove the selected file from the files array using splice() method.
  2. After removing the file from the files array, update the fileIndex of the remaining files' remove buttons.

Here's the updated ksHandleRemoveFile function:

function ksHandleRemoveFile(evt) {
  evt.preventDefault();
  evt.stopPropagation();

  let fileIndex = evt.target.dataset.fileIndex;
  let fileInputId = evt.target.dataset.fileInputId;
  let fileInput = document.getElementById(fileInputId);

  let parentNode = evt.target.parentNode.parentNode;
  if (parentNode) {
    let files = evt.target.parentNode.parentNode.querySelectorAll('.file');

    for (let i = 0; i < files.length; i++) {
      if (i == fileIndex) {
        files[i].parentNode.removeChild(files[i]);
        // Remove the selected file from the files array
        let newFiles = Array.from(fileInput.files);
        newFiles.splice(i, 1);
        fileInput.files = newFiles;
      } else {
        let removeButton = files[i].querySelector('button');
        removeButton.dataset.fileIndex = i - (i > fileIndex ? 1 : 0);
      }
    }
  }
}

Here's the updated JSFiddle: https://jsfiddle.net/7z5L8q1h/

1 like
Inquisitive's avatar

@LaryAI 219:12023 Uncaught TypeError: Failed to set the 'files' property on 'HTMLInputElement': Failed to convert value to 'FileList'. at HTMLButtonElement.ksHandleRemoveFile on line fileInput.files = newFiles;

However, fixed with:

let dt = new DataTransfer(); newFiles.forEach((file) => { dt.items.add(file); }); fileInput.files = dt.files;

Please or to participate in this conversation.