1

I'm creating a follow/unfollw buttons for different members in a system. I'm having an issue with jQuery event not being fired after html is rendered again in the same div where the buttons are. The follow/unfollow-buttons works FIRST time - always, but never on second try. Other things that are depending on javascript still works so it's not an error in js either.

//html snippet
<div id="start-members">
<div class="content">
    <div class="result">
        <div class="items-column member"><div class="image-holder">
        <img src="imagefile"></div>
        <span class="button-section">
        <a href="#" data-userid="61" class="follow button trans-effect follow-user"><span class="following-text">Follow</span><span class="unfollow-text">Unfollow</span></a>
        </span>
        <div class="clearfix"></div></div>

        <div class="items-column member"><div class="image-holder">
        <img src="imagefile"></div>
        <span class="button-section">
        <a href="#" data-userid="95" class="follow button trans-effect follow-user"><span class="following-text">Follow</span><span class="unfollow-text">Unfollow</span></a>
        </span>
        <div class="clearfix"></div></div>

        <div class="items-column member"><div class="image-holder">
        <img src="imagefile"></div>
        <span class="button-section">
        <a href="#" data-userid="104" class="follow button trans-effect follow-user"><span class="following-text">Follow</span><span class="unfollow-text">Unfollow</span></a>
        </span>
        <div class="clearfix"></div></div>

    </div>
</div>
</div>

//jQuery
//This returns html and put it into result-div above
function getLatestMembers() {
    var getLatest = $.ajax({
        type: 'GET',
        url: '/index.php/members/getlatest',
        dataType: 'json'
    });

    //If success, returning html
    getLatest.done(function(data) {
        $("#start-members .result").html(data);                
    });                        

    getLatest.fail(function(ts) {
        alert(ts.responseText);
    });            
}

//Toggle between following this user or not
$(".content .button-section").on('click', '.button.follow-user', function(e) {   
    e.preventDefault();
    //doing toggle of the button (to unfollow-user/follow-user)
    getLatestMembers(); //When having this call it renders the div latest members and next time this event is not fired. why?
});

//Unfollow user that has created this outfit
$(".content .button-section").on('click', '.button.unfollow-user', function(e) {   
    e.preventDefault();
    //doing toggle of the button (to unfollow-user/follow-user)
    getLatestMembers(); //When having this call it renders the div latest members and next time this event is not fired. why?
});

I've also tried just having getLatestMembers() in the event call. Next time the event is not fired.

//Unfollow user that has created this outfit - fired only once
$(".content .button-section").on('click', '.button.unfollow-user', function(e) {   
    e.preventDefault();
    getLatestMembers();
});

I hope I've described the scenario so you guys understand my problem/issue:-) (Question is: Why is not event fired more then once?)

bestprogrammerintheworld
  • 5,018
  • 6
  • 36
  • 67
  • you are replacing the button in getLatestMembers() – bansi Oct 03 '14 at 07:20
  • possible duplicate of [Event binding on dynamically created elements?](http://stackoverflow.com/questions/203198/event-binding-on-dynamically-created-elements) – mccannf Oct 03 '14 at 07:22
  • can you put those event binding sections of the code into a separate function, and call that function every time within the getLatest.done – Thangadurai Oct 03 '14 at 07:24

2 Answers2

3

Because when you update the section, you destroy the elements you've hooked the event on, and don't hook the events on the new elements that replaced them.

This code:

$(".content .button-section").on('click', function() { /*...*/});

finds elements that exist at that moment in time and hooks up a handler to them. But then this code:

$("#start-members .result").html(data);

destroys those elements and replaces them with new ones.

Use event delegation instead:

$("#start-members").on("click", ".content .button-section", function() { /*...*/});

That hooks the click event on the #start-members element, but tells jQuery to only trigger your handler if the event travels through elements matching the selector we give as the second argument. Since you don't destroy and recreate #start-members, the handler stays in place.

T.J. Crowder
  • 879,024
  • 165
  • 1,615
  • 1,639
  • i actually figured something similar out just after posting my question. But I used $(".content").on('click', '.button-section .button.unfollow-user', function(e) { - because .content isn't destroyed. Thanks for answer! :-) – bestprogrammerintheworld Oct 03 '14 at 07:21
  • @bestprogrammerintheworld: Sure, that'll work too, provided `.content` elements aren't created/destroyed dynamically. So would `.result` (with the same proviso). I picked `#start-members` because I wasn't sure there wouldn't be multiple `.content` or `.result` elements being created/removed dynamically (while I figured an element with an `id` probably wasn't). :-) – T.J. Crowder Oct 03 '14 at 07:24
  • :-) I just posted an answer to my own question, but I will of course accept your answer soon (when I'm allowed to) – bestprogrammerintheworld Oct 03 '14 at 07:25
0

Haha. Just because I posted this question I figured it out. In case some one else has similar issues...

I changed:

$(".content .button-section").on('click', '.button.unfollow-user', function(e) {   
    e.preventDefault();
    //doing toggle of the button (to unfollow-user/follow-user)
    getLatestMembers(); //When having this call it renders the div latest members and next time this event is not fired. why?
});

TO

$(".content").on('click', '.button-section .button.unfollow-user', function(e) {   
    e.preventDefault();
    //doing toggle of the button (to unfollow-user/follow-user)
    getLatestMembers(); //fired each time now
});
bestprogrammerintheworld
  • 5,018
  • 6
  • 36
  • 67