kartik-v / bootstrap-fileinput

An enhanced HTML 5 file input for Bootstrap 5.x/4.x./3.x with file preview, multiple selection, and more features.
http://plugins.krajee.com/file-input
Other
5.36k stars 2.4k forks source link

Drag and Drop doesn't update file list on html <input> element #388

Closed andrewschmidt-a closed 9 years ago

andrewschmidt-a commented 9 years ago

Reproduction Steps:

  1. initialize a file input with drop Zone enabled with id: 'yourID'
  2. add file by Drag and Drop
  3. goto a developer console and type the following:
    $('#yourID').get(0).files
  4. Now you should see that there is no files added However if you were to upload by the browse button then you would see them

Proposed Work around

  1. Allow the user to get the filestack from the plugin's function getFileStack()
  2. find some way to actually attach to dom element the file (I dont have a working copy of fileinput.js for this solution[yet])
kartik-v commented 9 years ago

Not sure you read the docs. Please do read the usage modes of the plugin.

Drag and drop can be used to read files only via AJAX and not via the native file input (NOR via FORM submission).

Basically files selected in HTML native file input cannot be manipulated or appended/changed via external javascript.

andrewschmidt-a commented 9 years ago

I did read your docs however I believe they are Incomplete.

How do you suggest that I check if there are files without uploading? I do not believe you have that capability yet.

andrewschmidt-a commented 9 years ago

Excuse my novice experience with Git Hub but this is my code

This allows me to do $('#yourID').fileinput('getFileStack') to return the array of files in the queue

//FileInput plugin definition
    $.fn.fileinput = function (option) {

        if (!hasFileAPISupport() && !isIE(9)) {
            return;
        }

        var args = Array.apply(null, arguments);
        args.shift();
        var retVals = []; //-as

        this.each(function () {
            var $this = $(this), data = $this.data('fileinput'), defaults,
                options = typeof option === 'object' && option,
                lang = options.language || $this.data('language') || 'en';

            if (!data) {
                defaults = $.extend({}, $.fn.fileinput.defaults);
                if (lang !== 'en' && !isEmpty($.fn.fileinputLocales[lang])) {
                    defaults = $.extend(defaults, $.fn.fileinputLocales[lang]);
                }
                data = new FileInput(this, $.extend(defaults, options, $this.data()));
                $this.data('fileinput', data);
            }

            if (typeof option === 'string') {
                //console.log(data[option].apply(data, args));
                retVals.push(data[option].apply(data, args)); // changed to push to array -as
            }
        });
        //this whole retVal logic was changed up  -as
        //will return this when there is no return vals like before
        if(retVals.length == 1){
            return retVals[0];
        }else if(retVals.length == 0){
            return this;
        }else{
            return retVals;
        }
    };
kartik-v commented 9 years ago

Just reiterating:

In AJAX mode --- you will receive files on your server code BUT CANNOT use the NATIVE file input to read file data on client. However you can use advanced features like drag & drop, append/remove files before upload etc.

In NON-AJAX (normal form submission) you ll receive files on your server code AND also be able to read data for the native file input. However you cannot drag & drop files, or append/remove files before upload.

Just check docs for minFileCount and maxFileCount properties to do checks for count of files.

While maxFileCount is comprehensive in checks ... minFileCount may not be completely comprehensive because plugin will not know when to do the minimum file count check exactly. It does do this check before upload but if you use initalPreview user can violate this check.

It is recommended therefore that the most straightforward and comprehensive method to do the check for AJAX submissions is to do it in your SERVER code that processes the files AND do a count check OR validate it with earlier server uploaded files if needed or any other use case and return an error or message if needed.

kartik-v commented 9 years ago

How do you suggest that I check if there are files without uploading? I do not believe you have that capability yet.

Read about minFileCount and maxFileCount in plugin docs and go through this plugin's page demo for minimum file count validation for AJAX submissions. Read the fine line comment and understand that depending on how you configure the plugin, you may need to also double up the validation via server code to be sure.

For min file counts - NOTE that technically this is an event which each individual developer will need to decide, when to be done and code accordingly. It cannot be done on file selection but probably at some other stage during form submission. (Doing this check on server will be more trusted way depending on scenario esp. if you have initialPreview set).

andrewschmidt-a commented 9 years ago

I still don't think you are following me. I want to get the file stack regardless to how many they insert. In my case they can insert however many they want I just want to know the amount on the client side before. (e.g. I want to pop up a confirm box "do you want to upload x files" where x is the number)

I understand if you don't want to open the file stack up to be accessed (like in my code I gave you) but I think you ought to, as I know it is useful for me and I am sure for others too.

kartik-v commented 9 years ago

Read about the various plugin events. Depending on how you have configured you need to use the right event. You can try using filebatchselected event or fileloaded event for example - they offer a method to access the filestack or file or reader instance.

andrewschmidt-a commented 9 years ago

Right,... I have looked through those I wanted it on upload but I could find a way to stop the upload if they didn't confirm...

So you just dont want to allow this or why not allow for a getFilestack method?

kartik-v commented 9 years ago

I am not convinced OR not clear why its needed - because precisely that's what events are intended for. These make you available the information needed (files in this case for filebatchselected) based on which you can trigger other actions. For example you can disable the upload button Or store data in a variable for future reference.

Note: If you want to abort/prevent the file upload from any other event ... you can read the events manipulation as described. For example, in your filebatchselected event you can return an object containing:

andrewschmidt-a commented 9 years ago

Sure but that event isnt what I needed. From what I understand file batchselected is when they are added or dragged&dropped. I would need a preupload sort of event.

I just thought it was strange that you essentially allowed me to execute any function in your function list but I couldn't get the return values. You also already have a getFileStack function. So I just manipulated the fileinput.js to allow it to return (see my code)

So I don't see why not have it return values. It is not as if you were trying to hide something from the user because the source is available anyhow

So I will just keep my changed version here so that I can directly call functions and I guess you'll just not agree with me.

kartik-v commented 9 years ago

If you have a suggestion for enhancement please raise a Pull Request (I do not see the code you mentioned you have posted).

Yes you can access any method in the plugin - so if that was the query - this issue will be mute ...if you want to know if you can access methods. Note that not all methods are documented for public use... because many internal methods can change in future - the public methods documented are listed here. But you can technically use the internal plugin methods as you can check from the code.

However, if you need to understand how to use functionality as intended in the plugin design and which will work irrespective of future expansions/ updates to the plugin - you need to use the documented methods and events - which I was trying to explain. Its anyway upto you to decide.

kartik-v commented 9 years ago

From what I understand file batchselected is when they are added or dragged&dropped. I would need a preupload sort of event.

BTW.. there are filepreupload or the filebatchpreupload events which allows you to detect preupload and gives access to all the information one needs. One can also abort upload from this event as explained in events manipulation.

Again this is the intended plugin design and best practice to allow developers to expand upon with minimal coding effort (without needing to modify plugin design) and should safely work with future updates. Of course I cannot enforce this.

andrewschmidt-a commented 9 years ago

My bad, sorry I thought I had created a pull request aswell as included my code inline

kartik-v commented 9 years ago

If you get the updated code... your use case can be achieved via ajax scenario 9. Its a simple few lines of code to trap the event (which you may anyway doing with your button click code).

I will need to think on your PR (because function/methods and their params may change with future updates and can break BC and each developer's code - so there needs to be a thought on segregating methods as private and public).