Search code examples
javascriptpythoneel

File OnChange method when called second time it takes the previous file which is selected first Time


I am using Eel package of python that help me to integrate Html/CSS/js with python so I am dynamically generating Html tags via JS based on input in a python file basically it's a chatbot and UI of that chatbot is created by Html/js

main.js that creates tags dynamically

eel.expose(selectPDF);
function selectPDF(moduleSelection){ // moduleSelection is coming from python
    console.log("select pdf called")
    var DemoDom = document.createElement("input");
    DemoDom.setAttribute('type','file'); //creating tag for input file
    DemoDom.setAttribute('name','myfile');
    DemoDom.id = "agenttext";
    DemoDom.setAttribute('class','selectButton');
    DemoDom.setAttribute('multiple','multiple');
    DemoDom.setAttribute('onchange','showname("'+moduleSelection+'")')
    chatBox.appendChild(DemoDom);

}
eel.expose(showname); //this is eel package syntax
function showname(moduleSelection){
    console.log("i am here")
    var name = document.getElementsByClassName('selectButton');
    var fileList = [];
    // if only one file is selected do this
    if(name[0].files.length === 1){
        console.log("File name: ", name[0].files[0].name)
        var temp = name[0].files[0].name;
        eel.getFileName(temp,moduleSelection); // passing file to python function getFileName
    }
    else{
        for (var i = 0; i < name[0].files.length; i++) {
            console.log("File name for loop: ", name[0].files[i].name)
           fileList.push(name[0].files[i].name); // push all file to list 
        }
        eel.getFileName(fileList,moduleSelection); // passing filelist to python function getFileName
    }
    return
}

Now when I call selectPDF() first time it creates input tag and call onchange method all working fine

but now When I call it the second time js again create input tag and call onchange method and it takes the previous file and not the new one that I want to select

see the image

Ignore red errors

JUST SEE THE FILE NAME: image.png

ignore all other red errors

as you can see in the image when I call "image to text" first time it works fine creates DOM and proceed further but when the second time I call "image to text" it creates DOM but select the previous file image.png instead of Sample.pdf

You can see the console file name it should select Sample.pdf instead of image.png when calling the second time


Solution

  • Seems like your app executes this code each time

    if(name[0].files.length === 1){
            console.log("File name: ", name[0].files[0].name)
            var temp = name[0].files[0].name;
            eel.getFileName(temp,moduleSelection); // passing file to python function getFileName
        }
    

    1. Index selection

    Is there a reason you're selecting the first index from name[0] each time? Maybe just checking for name.files.length would work?

    2. If/else algorithm

    If you structure your code a bit better, it might surprisingly work better. Try using the Javascript Array.forEach() method instead of your loop. It would look something like this

    function showname(moduleSelection) {
        console.log("i am here");
        var files = document.getElementsByClassName('selectButton');
        
        var fileList = [];
        if (files.length > 0) {
            files.forEach(file => {
                console.log("File name: ", file.files[0].name);
                fileList.push(file.files[0].name);
            })
            eel.getFileName(fileList, moduleSelection);
        }
        return;
    }
    

    I hope this will maybe hopefully help!

    EDIT:

    If u want to remove previous files after calling the files, you will have to mark the currently selected files at document.getElementsByClassName('selectButton') as already called.

    You can do this in various way, an example would be to change the class name from selectButton to selectButtonDone after the file name was pushed into the fileList[] array.

    You can do this particularly by executing file.className = 'selectButtonDone'; at the end of the files.forEach() function.