Do I need to unbind jquery event before remove element?
Asked Answered
C

3

47

I have a page using jquery-ui-dialog. Each time the dialog opens, page contents load in using ajax. Then it binds some event using jquery "on()". When the dialog close, it will empty its content.

The question is, do I need to unbind the events on ".ajax-content" before $.empty()?

edit: concern 1. any possible degrade JS performance? if I empty() hundreds of nodes this way.

concern 2. would remove element also remove events from memory(or whatever execution/evaluation chain of jquery)?

I am not doing anything to them for now. If the dialog open/close for many times without page refresh, would it cause any problem?

Code look like this:

<div id="jquery-dialog" class="container">
  <div class="ajax-content">
    some buttons....
  </div>
</div>

------after each ajax load------------
$(".ajax-content").on("click", ".button", function(event) {
  //handles the click
});

------on dialog close------------
$("#jquery-dialog").empty();
Cnemis answered 9/6, 2012 at 1:33 Comment(1)
+1: What a good question? I concern this too.Epicenter
E
56

Hey I know this is an old question but I believe the accepted answer is misleading.

Although it's correct to say that you will need to unbind events on raw JS to avoid memory leaks on old browsers (ehem IE), calling remove() or empty() will already do that for you.

So your current call to empty() should be enough, it doesn't need to be preceded by unbind()

From jQuery docs (http://api.jquery.com/empty/)

To avoid memory leaks, jQuery removes other constructs such as data and event handlers from the child elements before removing the elements themselves.

Eckart answered 17/7, 2013 at 20:7 Comment(1)
Thank you ...concise, to the point, and provided documentation reference. +1Brodeur
P
1

It's better to unbind but must.

Most browsers handle this correctly and remove those handlers themselves.

You can also see do-i-need-to-remove-event-listeners

Better way to handle this problem, you can use the Event Delegate.

Pasho answered 31/10, 2012 at 7:39 Comment(1)
Thanks for the link. Learned something new.Cnemis
B
-1

Oscar's answer is incomplete, if inside your partial (view that's loaded via ajax) you attached events using .on(), then you must call .off() before .empty().

Look in the following code, if .off() is not called, events assigned in p1.html via standard .click() handler are removed when calling .empty(), but events assigned in p2.html via .on() are not removed and re assigned each time the partial is loaded.

index.html

<html>
<body>
<script src="ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
    <div id='spi' style="padding: 20px; border: 1px solid #666;">
    </div>
    <br/>
    <a href="p1.html" class="spi">Load Partial 1</a> | 
    <a href="p2.html" class="spi">Load Partial 2</a>
    <script type="text/javascript">
    $(document).on('click', 'a.spi' , function(e) {
        e.preventDefault();

        /* 
        !!! IMPORTANT !!!
        If you do not call .off(), 
        events assigned on p2.html via .on()
        are kept and fired one time for each time p2.html was loaded
        */

        $("#spi").off();  


        $("#spi").empty();
        $("#spi").load($(this).attr('href'));
    });
    </script>
</body>
</html>

p1.html

This is the partial 1<br/>
<br/>
<br/>
<a href="javascript:void(0)" id='p1_l1'>Link 1</a>
<br/><br/>
<a href="javascript:void(0)" id='p1_l2'>Link 2</a>
<br/><br/>
<a href="javascript:void(0)" id='p1_l3'>Link 3</a>


<script type="text/javascript">
    $("#p1_l1").click(function(e) {
        e.preventDefault();
        console.debug("P1: p1_l1");
    });
    $("#p1_l2").click(function(e) {
        e.preventDefault();
        console.debug("P1: p1_l2");
    });
</script>

p2.html

This is the partial 2<br/>
<br/>
<br/>
<a href="javascript:void(0)" id='p2_l1'>Link 1</a>
<br/><br/>
<a href="javascript:void(0)" id='p2_l2'>Link 2</a>


<script type="text/javascript">
    $("#spi").on('click', 'a', function(e) {
        e.preventDefault();
        console.debug( 'P2: ' + $(this).attr('id') );
    });
</script>
Bullate answered 10/4, 2014 at 12:34 Comment(1)
On your call to .on() on p2.html the event is attached to '#spi' (not to the inner 'a' elements). When you then .empty() it later on, you are unbinding events attached to the 'a' elements but the ones on '#spi' persist.I think that if you re-write $("#spi").on('click', 'a', function) to $("#spi a").on('click', function) you'll have the effect you want.Eckart

© 2022 - 2024 — McMap. All rights reserved.