Valrus
Valrus

Reputation: 5

Event Delegation breaks after ajax call

I'm working on a project where I have a table of elements, if a row is clicked I load details into another div, make an edit and re-load the list(if something is deleted or list needs to be resorted). I'm doing this through an $.ajax call, however upon return and the html updated, my click events stop working.

I am using $.on to bind them all to a parent element as per many answers here on stack, and everything works great for the first pass through, but all my links break after that pass. It also breaks ALL my events, even ones that are outside the div I am updating.

I am using a combination of jquery, Gumby and Code Igniter on this project.

This is where I bind everything...

$(document).ready(function() { 
                $('#eventlisting').on("click",".eventrow",getEvent);
                $('#eventdetails').on("click","#eventupdate",updateEvent);
                $('#eventdetails').on("click","#eventdelete",deleteEvent);
                $('#eventdetails').on("click",'#eventsubmit',submitEvent);
            });

My main html... Note that the in-line onclick event stops working as well.

  <nav class="navbar">
        <div class="row">
            <ul class="eight columns">
                <li><h1 class="logo">Event Manager</h1></li>
                <li><div class="medium primary btn"  ><a class="neweventbttn" onclick="newEvent();">Enter New Event</a></div></li>
            </ul>
        </div>
    </nav>
<div class="container" id="maindiv">
   <section id="eventlisting" class="row"> //this is what gets re-set
    <table>
            <tr>
                    <th>Event Id</th>
                    <th>Division</th>
                    <th>Title</th>
                    <th>Date</th>
                </tr>
            <tr class="eventrow" name="eventlink"  value="62">
                <td>62</td>
            <td>type</td>
                    <td>A title of here</td>
                    <td>A date here</td>
             </tr>
            ...
            </table>
    <div id="eventdetails" class="five columns">
              //this holds my edit details section where updates are done
    </div>
</section>              
</div>      

My Ajax that initially populates the details area...

function getEvent() {
   var eventid = $(this).attr('value');
   //do an ajax request here.
   var jqxhr = $.ajax({url:baseurl+"manager/eventget",
                         type:'POST',
                         data: {'eventid':eventid}
                      })
        .done(function() {
          $('#eventdetails').html(jqxhr.responseText);
        })
        .fail(function() {
             $('#eventdetails').append(jqxhr.responseText).append(jqxhr.statusText);
         })
         .complete(function() {
                $('#startdate').datepicker({dateFormat:"yy-mm-dd"});                                
                 Gumby.initialize('radiobtns');
          });
   }

One of my Ajax calls, they are all pretty similar, so if one works they all should.

 function updateEvent() {
   //submit to the database, update event.
    var mydivision = $('input[checked]').val();
    var mydata = $('#editeventform').serialize();
    mydata = mydata.concat('&division=',mydivision);
    var jqxhr_update = $.ajax({url:baseurl+"manager/eventupdate",
                               type:'POST',
                               data: mydata
                            })
        .done(function() {
           if(jqxhr_update.responseText.indexOf('~')>0) {
              var mymessagedata = jqxhr_update.responseText.substr(0,jqxhr_update.responseText.indexOf('~'));
              var mylistdata = jqxhr_update.responseText.substr(jqxhr_update.responseText.indexOf('~')+1);
              $('#eventdetails').html(mymessagedata);
              $('#eventlisting').html(mylistdata);  //This is where I re-set the list
            } else {
              $('#eventdetails').html(jqxhr_update.responseText);
            }
          })
         .fail(function(){
             alert('failure'+jqxhr_update.responseText);
             $('#eventdetails').append(jqxhr_update.responseText).append(jqxhr_update.statusText);    
     });
  }

Upvotes: 0

Views: 1145

Answers (2)

Tim Hobbs
Tim Hobbs

Reputation: 2017

You have to bind to something that doesn't get wiped out - which you are not. When the eventlisting contents are overridden, your events on eventdetails are removed. You need to use maindiv or some other parent container.

Upvotes: 1

Bergi
Bergi

Reputation: 664425

$('#eventlisting').html(mylistdata);  //This is where I re-set the list

Then this is the place where you remove all listeners from the descendants of #eventlisting, including your #eventdetails. If you do use event delegation, you must bind to the non-changing parent element. So change your code to

$(document).ready(function() { 
    $('#eventlisting')
      .on("click", ".eventrow", getEvent);
      .on("click", "#eventupdate", updateEvent);
      .on("click", "#eventdelete", deleteEvent);
      .on("click", '#eventsubmit', submitEvent);
});

Upvotes: 1

Related Questions