File Input not recognizing file upload 2nd time

2.1k views Asked by At

I am trying to use the Krajee Bootstrap File Input to upload a file. The way it works now is I have a button, that when clicked, opens a Bootstrap modal dialog and the input file tag is inside that modal. The user clicks a browse button, selects a file, and the file gets uploaded. All of that works just fine!

My issue is if the modal is closed, then reopened again, the file input control no longer works. When I click browse, it lets me select a file, but the Krajee File Input control errors out and says:

You must select at least 1 file to upload.

Even though I select a file, it says that anyway. Like I stated before, it works fine on the first use, but after multiple uses, it starts getting that error. I imagine my issue is in the way I'm destroying and re-creating the control. Here is my modal dialog and file input control html code:

<div class="modal fade" id="modalUpload" tabindex="-1" role="dialog">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">Upload Profile Image</h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body">
                <div id="divFileInput">
                    <input id="fileFileUpload" type="file" name="files"/>
                </div>
                <div id="divCropper">
                    <img id="imgCropperPicture" alt="profile" />
                </div>
            </div>
        </div>
    </div>
</div>

Here is my relevant client side code (It's written in TypeScript 2.8):

   $("#fileFileUpload").fileinput({
        showPreview: true,
        uploadAsync: false,
        uploadUrl: '/fileupload',
        allowedFileExtensions: ['jpg', 'jpeg', 'png'],
        allowedPreviewTypes: ['image'],
        uploadExtraData: { memberId: $("#hidMemberId").val() },
        resizeImage: true,
        theme: 'fa',
        minFileCount: 1,
        maxFileCount: 1,
        dropZoneEnabled: false,
        showRemove: false,
        showUpload: false,
        showCancel: false,
        overwriteInitial: true
    }).on("change", () => {
        $("#fileFileUpload").fileinput(("upload") as any).on("filebatchuploadsuccess", (event, data: any) => {
            this.uploadFinished(data);
        });
    });

    $('#modalUpload').on('hidden.bs.modal', (e) => {
        $("#divCropper").hide();
        $("#divFileInput").show();

        $("#fileFileUpload").fileinput(("clearStack") as any);
        $("#fileFileUpload").fileinput(("clear") as any);
        $("#fileFileUpload").fileinput(("destroy") as any).fileinput({
            showPreview: true,
            uploadAsync: false,
            uploadUrl: '/fileupload',
            allowedFileExtensions: ['jpg', 'jpeg', 'png'],
            allowedPreviewTypes: ['image'],
            uploadExtraData: { memberId: $("#hidMemberId").val() },
            resizeImage: true,
            theme: 'fa',
            minFileCount: 1,
            maxFileCount: 1,
            dropZoneEnabled: false,
            showRemove: false,
            showUpload: false,
            showCancel: false,
            overwriteInitial: true
        }).on("change", () => {
            $("#fileFileUpload").fileinput(("upload") as any).on("filebatchuploadsuccess", (event, data: any) => {
                this.uploadFinished(data);
            });
        });
    });

So basically, I'm initializing the file input control for the first time. The $('#modalUpload').on('hidden.bs.modal' ...) code is code that gets executed when the BootStrap modal is closed. What I'm doing is calling the destroy method on the file input control, then recreating it exactly as before.

Any help on getting this working would be appreciated!

3

There are 3 answers

0
Icemanind On BEST ANSWER

I seemed to figure this out for myself. In case anyone else runs into this issue, the problem is because the destroy method does not remove the event handlers. So what was happening is my change event handler was getting called, but because #fileFileUpload was destroyed, it was throwing a JS error in the console window. So what I had to do was just add the line below before calling the destroy method:

$("#fileFileUpload").off("change");

I placed that line before calling the destroy method and now everything works as expected.

0
tmpmachine On

The first time you initialize the plugin, it will attach a listener to the -- in this case -- fileFileUpload input. When the modal is closed, it trigger the input deletion but not the listener. And so when this line is triggered :

$("#fileFileUpload").fileinput(("destroy") as any).fileinput ...

it's actually creating a new element and attach the listener, but the old listener still active and so caused your program not working as expected.

You need to remove the listener when the modal is closed.

0
Azee On

I had the same problem even without a modal.

I now just call destroy method before I init the file input. See commit

$("#file-data").fileinput('destroy');
$("#file-data").fileinput({
    previewFileType: "any",
    uploadUrl: "BLAH",
    maxFileSize: BLAHBLAH
});
$("#file-data").on(
    "fileuploaded",
    function (event, file, previewId, index) {
        DO_SOMETHING
    }
);