0

From the Router, I create a Search View with the following code:
(The if is to only create a new View where one does not already exist, since the View never changes.)

search: function () {
    if (!this.searchView) {
        this.searchView = new SearchView();
    }
    $('#content').html(this.searchView.el);
    this.headerView.selectMenuItem('search-menu');
},

In the View, I have an events hash, binding a click event to a search button:

events: {
    "click .search-query": "search"
},

This results in the event only firing the first time the search button is used.
Removing the if from the search function solves the problem.

This however does not seem to be the correct way to approach this, since the View should not need to be recreated (reinitialized and re-rendered).

An attempted fix:

I attempted to add this.delegateEvents(); to the render function of the Search View as follows (while leaving the if in the search function), but it did not solve the problem:

render:function () {
    console.log('rendering search...');
    $(this.el).html(this.template());
    this.delegateEvents();
    return this;
},


Any suggestions would be appreciated.

DavidS
  • 15
  • 7
  • possible duplicate of [using a single div as a container for multiple backbone views losing event bindings](http://stackoverflow.com/questions/10707911/using-a-single-div-as-a-container-for-multiple-backbone-views-losing-event-bindi) – mu is too short Aug 31 '13 at 20:53

1 Answers1

1

Since you're not calling render() again, delegateEvents won't be called again. You can just call delegateEvents directly in your router. This is just an example; there are probably more elegant ways to do it.

delegateEvents basically rebinds the events to your view. This is useful if the html of your views gets removed from the dom. That looks like what is happening in your example.

search: function () {
    if (!this.searchView) {
        this.searchView = new SearchView();
    }
    $('#content').html(this.searchView.el);
    this.searchView.delegateEvents();
    this.headerView.selectMenuItem('search-menu');
}
Gohn67
  • 10,608
  • 2
  • 29
  • 35
  • The `.html()` call intentionally kills the events (further discussion [over here](http://stackoverflow.com/a/10708775/479863) if you're interested), the elegant solution IMO is to create and destroy views as needed instead of trying to reuse them. – mu is too short Aug 31 '13 at 21:02
  • Thanks @Gohn67 , that solved it. However, it is sometimes preferable to remove views, and recreate them where needed, and in this case, I realised that I did not need to preserve the view. – DavidS Nov 14 '13 at 12:16
  • Thanks @muistooshort, for pointing this out. Your links are definitely worth reading for anyone wondering whether to reuse or recreate elements. Additionally, I also found the following useful info: [Backbone.js : repopulate or recreate the view?](http://stackoverflow.com/questions/7567404/backbone-js-repopulate-or-recreate-the-view). – DavidS Nov 14 '13 at 12:31
  • In addition, the this related answer and comments provides information on [binding and unbinding events](http://stackoverflow.com/questions/14041042/backbone-0-9-9-difference-between-listento-and-on/14042632#14042632). – DavidS Nov 15 '13 at 10:13