1

I encountered an issue using jQuery's .delegate() method on IE8 when removing the elements to which my delegate handler was attached. Here's the scenario: I had a table with rows that each had a delete button. The rows were created dynamically, so the delete button was wired up using delegate to handle the click events. When it came time to remove the last row, the entire table was removed (table was only created once there was a value to create at least one row.) This worked fine just about everywhere with the one exception of IE8. Even then, it worked on some pages, but just not one (the exact same code was used on each page.) For this one particular page, deleting that last row would generate a js error in IE8 stating "Object required" - the offending line being in the jQuery code for delegate.

So the question is, what's the best practice with handlers when some of the DOM elements those handlers are using are removed? Should undelegate be called at some point, and if so, where?

kinakuta
  • 9,029
  • 1
  • 39
  • 48

2 Answers2

3

Use jQuery's .remove() method:

"Use .remove() when you want to remove the element itself, as well as everything inside it. In addition to the elements themselves, all bound events and jQuery data associated with the elements are removed."

Or the .empty() method to remove all children but keep the top level element.

nnnnnn
  • 147,572
  • 30
  • 200
  • 241
  • @Reigel - Well I wondered, but OP doesn't say and perhaps `.html()` or `.detach()` or plain DOM methods are being used. Question did ask for "best practice", so I've answered that... – nnnnnn Feb 17 '12 at 03:14
  • 1
    So this brings up a good point and maybe the best practice question is misplaced. The table is being created in a backbone view using .html() If the attached backbone collection has at least one model in it, the table html is built and placed in a container using .html - if the last item in the collection is removed, the html is set to an empty string. Maybe the real issue is I need a better way to create and remove the DOM elements in my view code? – kinakuta Feb 17 '12 at 03:27
  • Well the jQuery doco for the `.html()` method doesn't mention it (that I can see), but I just took a quick look at the code and it seems it tries to clean up the events and data for the existing html before replacing/removing it (I don't know if that's true for old versions; I was looking at 1.7.1). – nnnnnn Feb 17 '12 at 03:47
  • FWIW, the current version of jQuery's `html()` documentation does say that it unbinds event handlers. http://api.jquery.com/html/ – Craig Walker May 09 '13 at 21:44
0

Kinakuta, from what you say it may simply be question of setting up the delegation correctly and phrasing the removal appropriately, rather than the use or not of remove() per se. It's hard to see why only IE8 should misbehave but probably some IE8 issue in jQuery.

With jQuery 1.7+ .on() replaces .bind(), .live() and .delegate() and may offer a way ahead. I would be looking to do something like this:

$("#myContainer").on("click", "button.delete", function(event){
    $(this).closest("tr", "#myContainer").remove();
});

You can no doubt achieve similar with .delegate() if you are using jQuery <1.7 .

As far as I can tell, it shouldn't matter, at the point of row removal, that the table and/or its rows were generated with MVC or any other generation method.

Beetroot-Beetroot
  • 18,022
  • 3
  • 37
  • 44