Backbone.View: delegateEvents not re-binding events to subview
backbone.js, javascript, jquery
Solution
To preserve the bindings you could do three things.
Use $.append instead of $.html
Using `$.append` will keep your bindings intact and also take care that you don't lose any sibling content.
Just re-render without re-attaching
In your code you re-render your view and also re-attach it's content. This is not necessary. Simply calling `v.render()` will achieve the same visual result but keep your bindings intact.
var v = new MainView();
$("#area1").html(v.render().$el); // binds work fine
// do some work... then re-render…
v.render(); // keeps event binds
$("#area1").append(v.render().$el); // works too
Use $.empty() before calling $.html()
According to the jQuery documentation for $.html(htmlString)
If you are keeping references to these DOM elements and need them to be unchanged, use .empty().html( string ) instead of .html(string) so that the elements are removed from the document before the new string is assigned to the element.
The important part is that $.html expects an html string, not elements and also unbinds any event handlers present on child nodes. The only way I can explain this behavior is that somehow through transformation of the dom tree to a string and vice versa the events get removed. Interestingly enough, using $.empty() as mentioned in the documentation solves the problem.
// any $.html reference needs to have an $.empty too
this.$el.empty().html(this.subView.render().$el);
// and then later for your mainView
$("#area1").empty().html(v.render().$el);
Problem
I have broken down this issue into the smallest example possible (i.e., it's only to demonstrate the problem, not to necessarily represent a real-world scenario). Let's say I have a parent view ("MainView" here) that contains a child view ("SubView" here). If, at any point, I need to re-render the parent view (which thereby re-renders the child view), I am losing the event bindings in the child view, despite calling `delegateEvents`. A jsfiddle can be found here: http://jsfiddle.net/ya87u/1/ Here is the code in full: ``` var MainView = Backbone.View.extend({ tagName : "div", initialize : function() { this.subView = new SubView(); }, render : function() { this.$el.html(this.subView.render().$el); // .html() breaks binds this.subView.delegateEvents(); // this re-establishes them return this; } }); var SubView = Backbone.View.extend({ tagName : "div", events : { "click .button1" : "onButtonPress" }, onButtonPress : function() { alert("Button pressed"); }, render : function() { var html = "<button class='button1'>Button1</button>"; this.$el.html(html); return this; } }); var v = new MainView(); $("#area1").html(v.render().$el); // binds work fine // do some work... then re-render... $("#area1").html(v.render().$el); // breaks event binds ``` I do not understand why this is happening. Any input would be greatly appreciated.