jQuery File Upload not working when file input dynamically created
Asked Answered
H

4

6

i am using this jquery uploader (http://blueimp.github.io/jQuery-File-Upload/basic.html) and it works fine when the file input is put in the raw code of the site, however i am dynamically appending the fields with jquery and it doesnt work. here is the jquery to trigger the upload:

$('.fileupload').fileupload({
    dataType: 'json',
    done: function (e, data) {
        $.each(data.result.files, function (index, file) {
            alert(file.name);
            //$('<p/>').text(file.name).appendTo(document.body);
        });
    }
});

and this is what SHOULD trigger the upload:

<input class="fileupload" type="file" name="files[]" data-url="uploads/">

Here is the code that is appended by jquery:

$(document).on('click','.addItem', function(){
            $('<!--ROW START-->\
                <form class="widget-content item" data-url="uploads/">\
                    <div class="row">\
                        <div class="col-md-3"><input type="text" class="form-control" name="itemName[]"></div>\
                        <div class="col-md-3"><textarea class="auto form-control" name="itemDescription[]" cols="20" rows="1" style="word-wrap: break-word; resize: vertical;"></textarea></div>\
                        <div class="col-md-3"><textarea class="auto form-control" name="itemCondition[]" cols="20" rows="1" style="word-wrap: break-word; resize: vertical;"></textarea></div>\
                        <input type="hidden" class="itemId" name="itemId[]" value="">\
                        <input type="hidden" name="itemInventoryId[]" value="<?=$_GET["inventory_id"]?>">\
                        <input type="hidden" name="itemParent[]" value="'+$(this).closest('.formHolder').data('parent-room')+'">\
                        <div class="col-md-2">\
                            <div class="fileinput-holder input-group">\
                                <input class="fileupload" type="file" name="files[]">\
                            </div>\
                        </div>\
                        <div class="col-md-1 align-center"><i class="save icon-ok large"> </i>&nbsp;&nbsp;&nbsp;<i class="delete icon-trash large"> </i></div>\
                    </div>\
                </form>\
            <!--/ROW END-->').fadeIn(500).appendTo($(this).parents().siblings('.items'));
            $(this).parent().parent().siblings('.widget-header, .header-margin, .hide').removeClass('hide').fadeIn();
        });

like i say, when i add it into the actual code, not dynamically its fine. Can someone help please?

Hadwin answered 19/10, 2013 at 16:7 Comment(3)
Usually this occurs when you call the $.fileUpload before the input element is appended to body. Try calling it after the element is created and appended.Disease
I've popped it at the bottom of the document, no luck :(Hadwin
ive added the code that gets appended, so you can seeHadwin
A
19

This is because you bind fileupload event before element is added.

Try moving your code into callback function which will be executed after you create input element. Since appendTo() doesn't support callback, you can use each(callback):

$('code_that_you_append').appendTo('some_element').each(function () {
    // here goes $('.fileupload').fileupload({ ... }) function
});

If you need to bind event to .fileupload in multiple places in code, you can create a function to avoid code repetition, like this:

function bindFileUpload() {
    $('.fileupload').fileupload({
        dataType: 'json',
        done: function (e, data) {
            $.each(data.result.files, function (index, file) {
                alert(file.name);
            });
        }
    });
};

and then call it in the callback, like before:

$('code_that_you_append').appendTo('some_element').each(function () {
    bindFileUpload();
});

I've created a little demo. It binds click instead of fileupload to simplify things (fileupload is external plugin...), but the general rule stays the same.

Antilogarithm answered 19/10, 2013 at 16:20 Comment(12)
Can you post example please?Hadwin
Added. If you could post the jQuery code that you use to append your form, I'd be able to make my example more precise.Berzelius
so it needs to go in with the code that i append? I'm adding multiple items so is this best practice?Hadwin
Code has been added :)Hadwin
I've updated my answer to show how to avoid code repetition in case you need to bind this event in multiple places.Berzelius
Does this bindFileUpload function go at the top or bottom of the page? I've placed it at the top and copied your code but it still doesnt fireHadwin
function bindFileUpload() { ... } can go at the top, as it is just a function definition. The rest of code ($(document).on(...) with callbacks inside) should go to the very bottom, just before closing </body> tag.Berzelius
Okay i've tried it, its literally doing nothing. It doesnt even load up anything in the console like it shouldHadwin
let us continue this discussion in chatHadwin
sorry, I've been wrong - I didn't know that appendTo won't accept callback, that's why it wouldn't work. I've edited my answer and provided a simple demo, hope that helps.Berzelius
Absolutely wonderful. Thank you so much, and thank you for coming back to this in your own time. You're a credit to the community friend, thank you!Hadwin
I think this answer has little mistake. On my answer I am trying to explain that. See my answer below.Menology
L
4

You need to use the jQuery live() function.

This tip I found worked for me.

jQuery fileupload for dynamically added input field

Lely answered 10/11, 2013 at 6:41 Comment(1)
If you can't get this solution to work, see this answer: #5541061 I had to replace my "$('.class').on('click, function(e){" wrapper with "$(document).on('click', '.class', function(e){" so that it would examine every click event.Mcdougald
R
2

Just bind the upload function with a static identifier at first. Here, 'document' is the static identifier. You can use anything like this that has not been added dynamically. Usually, document is used more often.

$(document).on('click', '.fileupload', function () {
    $('.fileupload').fileupload({
        dataType: 'json',
        done: function (e, data) {
            $.each(data.result.files, function (index, file) {
                alert(file.name);
                //$('<p/>').text(file.name).appendTo(document.body);
            });
        }
    });
});
Rheims answered 7/8, 2016 at 20:57 Comment(1)
This question is over 3 years old, the accepted answer worked fineHadwin
M
0

N.B: Please see accepted answer first.

I think accepted answer has little mistake. I just trying to recover that. On @Michał Rybak little demo you will see that every time we click add item another click event also will be added to previous added new link( add more then new link and see first new link show alert number of time new item). Because every time it add new link we again add click event to all new link elements.

 $('<p><a href="#" class="link">new link</a></p>').appendTo('body').each(function () {
      // bindClickToLink call every 'new link' and add click event on it
        bindClickToLink();
    });  

To solve that issues, instead add click event to all item we just add to newly created item. Here is my solution my demo .

Menology answered 25/12, 2015 at 3:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.