javascripttypescriptdom

onchange event not being triggered if input file is empty


I have this function, which asks the user for a file, and returns the File if selected, and (should) return null if nothing is selected.

async pickFile(allowed_extensions?: string[]): Promise<File | null> {
    const input = document.createElement('input');
    input.type = 'file';
    input.accept = allowed_extensions?.join(',') ?? '*';
    input.click();

    return new Promise((resolve) => {
        input.onchange = () => {
            if (input.files && input.files.length > 0) {
                resolve(input.files[0]);
            } else {
                resolve(null);
            }
        };
    });
}

If I select a file and confirm, it works normally. However, if I close the selection window, it seems the onchange event is not triggered. Is this behavior expected? If so, how could I handle it?

Reproducible example


Solution

  • onchange isn't triggered when closing the window.

    You should add another eventlistener to the cancel event that will trigger when you close the popup:

    function pickFile() {
      const input = document.createElement('input');
      input.type = 'file';
      input.click();
      return new Promise((resolve) => {
        input.onchange = () => {
          console.log('onchange triggered');
          if (input.files && input.files.length > 0) {
            resolve(input.files[0]);
          } else {
            resolve(null);
          }
        };
        input.addEventListener("cancel", () => {
            console.log('Input canceled');
          resolve(null)
        });
      });
    }
    <button type="button" onclick="pickFile()">Click Me!</button>