Jquery .on('change') not firing for dynamically added elements
Asked Answered
F

4

9

So I've got a page with the following structure

<div class="editCampaignBanner">
    <div>
    <hr>
    <label for="file">Upload a new image</label>
    <input id="file" type="file" name="file" class="valid">
    <label for="NewImageURLs">Link URL (Optional)</label>
    <input id="NewImageURLs" type="text" value="" name="NewImageURLs">
    <hr>
    </div>
</div>

and I've written some jquery thus:

$('div.editCampaignBanner input:file').on('change', function () {
        var value = $(this).val();
        var div = $(this).parent();
        var html = '<div>'+ div.html() + '</div>';
        if (value.length > 0) {
            div.after(html);
        }
        else if ($(this) > 1) {
            div.remove();
        }
    });

so when I enter an element into the file it generates a div under the previous one:

    <div class="editCampaignBanner">
        <div>
        <hr>
        <label for="file">Upload a new image</label>
        <input id="file" type="file" name="file" class="valid">
        <label for="NewImageURLs">Link URL (Optional)</label>
        <input id="NewImageURLs" type="text" value="" name="NewImageURLs">
        <hr>
        </div>
        <div>
        <hr>
        <label for="file">Upload a new image</label>
        <input id="file" type="file" name="file" class="valid">
        <label for="NewImageURLs">Link URL (Optional)</label>
        <input id="NewImageURLs" type="text" value="" name="NewImageURLs">
        <hr>
        </div>
    </div>

But now, despite the event being registered using .on() the second file input in the div does not fire the event. What am I missing?

Fruin answered 18/10, 2012 at 8:25 Comment(0)
A
13

Replace

$('div.editCampaignBanner input:file').on('change', function () {

by

$('div.editCampaignBanner').on('change', 'input:file', function () {
Ange answered 18/10, 2012 at 8:26 Comment(2)
right, so you bind the on to the document with a selector! Excellent ta!Fruin
As you don't seem to remove div.editCampaignBanner, you may use it as base for your on instead of the document.Prelatism
F
4
$(document).delegate("div.editCampaignBanner input:file", "change", function() {
  //code goes here
});


$(document).on('change', 'div.editCampaignBanner input:file', function () {
 //code goes here
});

Attach a handler to one or more events for all elements that match the selector, now or in the future, based on a specific set of root elements. As of jQuery 1.7, .delegate() has been superseded by the .on() method. For earlier versions, however, it remains the most effective means to use event delegation. More information on event binding and delegation is in the .on() method.

Differences Between jQuery .bind() vs .live() vs .delegate() vs .on()

Fishworm answered 18/10, 2012 at 8:30 Comment(5)
I said both are possible. I don't know which jquery version he's using.Fishworm
He uses on, so obviously he has at least 1.7.Prelatism
I was showing him possibilities and he can go through and learn. Hope it's not a crime to show the possibilities of a scenario.Fishworm
When somebody uses the right function, there is no point in reminding him the list of functions he should not use.Prelatism
like I said I was pointing the possibilities and if you read the link I have posted at the end, That article shows which is the best method to use and what are the options. I was being nice showing him options available.Fishworm
M
1

try this:

$('div.editCampaignBanner').on('change','input:file', function () {
        var value = $(this).val();
        var div = $(this).parent();
        var html = '<div>'+ div.html() + '</div>';
        if (value.length > 0) {
            div.after(html);
        }
        else if ($(this) > 1) {
            div.remove();
        }
    });
Meill answered 18/10, 2012 at 8:28 Comment(0)
I
0

May be use $.live() jquery method, its deprecated but works for me:

$('div.editCampaignBanner input:file').live('change', function () {
        var value = $(this).val();
        var div = $(this).parent();
        var html = '<div>'+ div.html() + '</div>';
        if (value.length > 0) {
            div.after(html);
        }
        else if ($(this) > 1) {
            div.remove();
        }
    });

more info : http://api.jquery.com/live/

if you are reluctant on using the latest (.on()) use it like this :

function fileChanged(ele){
    var value = ele.val();
    var div = ele.parent();
    var html = '<div>'+ div.html() + '</div>';
    if (value.length > 0) {
        div.after(html);
    }
    else if (ele > 1) {
        div.remove();
    }
    $('div.editCampaignBanner').unbind().on('change','input:file', function () {
        fileChanged($(this))
    });
}
$(function(){
    $('div.editCampaignBanner').on('change','input:file', function () {
        fileChanged($(this))
    });
});
Ironware answered 18/10, 2012 at 8:30 Comment(1)
Just to note, as of JQuery 1.7 live is actually identical to on (jquery4u.com/jquery-functions/on-vs-live-review/#.UH-6cMW5_mc) There are significant problems with live, hence it's replacementFruin

© 2022 - 2024 — McMap. All rights reserved.