1

At first I made a simple array just inside the .js file and wrote the function to make list items from it. Then clicking on freshly created li elements should do something.

//This code works

dic[0] = "decir";
dic[1] = "querer";
dic[2] = "poder";


$(document).ready(
    function verbsarray() {

        for (var i = 0; i < dic.length; i++) {      
                var verbo = dic[i];                         
                verbos += "<li class='h_li'>" + verbo + "</li>\n";
        };          
        $('ul.h_list').html(verbos);                       
});    

$(".h_li").click(function() {
    alert("it works!");
    //Dollar finds .h_li here
}

Since that was a prototype, then I developed that function to take items not from the static array, but from loaded JSON. Function parses the needed items and again makes list items from them.

But the other function (that looks for clicked <li class="h_li">) now doesn't work...

//this doesnt work :-( 

function verbos_from_json () {

    $.getJSON('verbos.json', function verbsarray(vjson) {
        for (var i = 0; i < vjson.data.length; i++) {       
            verbo = vjson.data[i].verb;                         
            verbos += "<li class='h_li'>" + verbo + "</li>\n";
        };      

        $('ul.h_list').html(verbos);
        });         
};

$(".h_li").click(function() {
    alert("it works?.. no");
}

3 Answers3

1

For dynamically rendered elements, you need to use delegate binding with jquery. Instead of click():

$(".h_li").click(function() {
    alert("it works?.. no");
};

use on():

$(".h_list").on('click', '.h_li', function() {
    alert("it works?.. no");
};
wahwahwah
  • 3,254
  • 1
  • 21
  • 40
  • 2
    The idea is correct but you didn't use `.on()` correctly for delegation. You need to provide a selector as the second argument. `$('.h_list').on('click', '.h_li', function () { ... });`. In addition, when delegating, attach the event listener to the parent (i.e. `.h_list`) not the the individual `.h_li` elements themselves. – War10ck Oct 08 '15 at 17:30
  • @War10ck - that's correct - clerical error. Thanks for pointing it out. I'll update the answer – wahwahwah Oct 08 '15 at 17:31
  • Your edit is almost there. Update the first selector to be the parent `.h_list` and not the individual element `.h_li`... – War10ck Oct 08 '15 at 17:32
  • Thanks! This solution works! – Mike Miroshnikov Oct 08 '15 at 20:15
1

You have to integrate your listening function in your verbos_from_json

function verbos_from_json () {

$.getJSON('verbos.json', function verbsarray(vjson) {
    for (var i = 0; i < vjson.data.length; i++) {       
        verbo = vjson.data[i].verb;                         
        verbos += "<li class='h_li'>" + verbo + "</li>\n";
    };      

    $('ul.h_list').html(verbos);
 //****************************************************************
    //}); // bad place : it was a typo ( edited after discussion ) 
 //****************************************************************

// THIS PART HAS MOVED IN
$(".h_li").click(function() {
// better to off before (if is safe for you) to prevent multiple event
// $(".h_li").off('click').click(function() {

    alert("it works?.. no");
}
}); // it was a typo ( edited after discussion ) 
};
Anonymous0day
  • 3,012
  • 1
  • 14
  • 16
  • This is incorrect. It doesnt matter whether the click event handler is within the function closure but I would think its better the way the OP has it now. – wahwahwah Oct 08 '15 at 17:27
  • No it is very important ! $.getJson is asynchronous and you just ask to listen to a list of element and after you want it interact whith new ones without binding to the newer ones ! – Anonymous0day Oct 08 '15 at 17:30
  • That is not correct either. Check out my answer (with the help of Warlock) and the duplicate comment on the OP – wahwahwah Oct 08 '15 at 17:35
  • this is exactly what i have said ! – Anonymous0day Oct 08 '15 at 17:37
  • For this to work like you've shown, the `$('.h_li').click(...);` part would need to be inside `$.getJSON()`'s success callback function. – War10ck Oct 08 '15 at 17:40
  • you're right there were copy/paste error ! this my fault ! But the explanations was correct – Anonymous0day Oct 08 '15 at 17:43
  • Much better. This method will work, however notice my comment on _@madi_'s answer about the advantages of using event delegation. Either way, this is now a valid solution as well... – War10ck Oct 08 '15 at 17:43
  • I agree totaly with delegation ! – Anonymous0day Oct 08 '15 at 17:47
1

Since the elements are added after ajax call. The click event is not attached to new elements that are added asynchronously . I will do this:

function verbos_from_json () {

    $.getJSON('verbos.json', function verbsarray(vjson) {
        for (var i = 0; i < vjson.data.length; i++) {       
            verbo = vjson.data[i].verb;                         
            verbos += "<li class='h_li'>" + verbo + "</li>\n";
        };      

        $('ul.h_list').html(verbos);

        // bind here
        $( ".h_li" ).bind( "click", function() {
                alert( "It works" );
        });
    });         
}; 

{OR}

As mentioned by War10ck delegation can be done instead of binding in the json.

Change:

$(".h_li").click(function() {
    alert("it works?.. no");
};

To:

$( ".h_list" ).delegate( ".h_li", "click", function() { 
      alert("It works?.....no") 
})
madi
  • 5,612
  • 5
  • 36
  • 48
  • 1
    Not a bad idea, though you'll have `n` number of event listeners where `n = vjson.data.length` as oppose to just one event listener if delegated using `.on()`. It's more memory intensive though probably not enough to make a noticable difference within the UI. – War10ck Oct 08 '15 at 17:38
  • In that case , mike can use $( ".h_list" ).delegate( ".h_li", "click", function() { alert("It works?.....no") }); – madi Oct 08 '15 at 17:46
  • Thanks, but moving the click listener just under the json's load was my the first action. But that wouldn't help. – Mike Miroshnikov Oct 08 '15 at 23:13