Search code examples
javascriptasynchronousbackbone.jsbackbone-events

Asynchronously add events in backbone


In backbone, how do you asynchronously add events, based on other events. I want to allow click handlers on a certain set of buttons, but not until their containing button is clicked. Here's how I have things set up at the moment:

var ProductsView = Backbone.View.extend({


  events : {
        "click .filter-options-container" : "filterOptionContainerClick"
  },

  filterOptionContainerClick: function(e){
    $(e.currentTarget).addClass('active');
    //want to add an event to all .filter-options to allow them to trigger the filterOptionClick function when clicked
  },

  filterOptionClick: function(e){
    $('.filter-option').removeClass('active');
    $(e.currentTarget).addClass('active');
    $('.filter-options-container').removeClass('active');
  }

});

return ProductsView;

Solution

  • Instead of adding click handlers for sub-buttons whenever the container is clicked, you can use another approach:

    1. register sub-buttons' click handlers once with events map.
    2. add boolean property to the View to store state of the container click
    3. toggle that property in filterOptionContainerClick handler
    4. depends on the value of the property, allow/disallow clicking on sub-buttons

    So the code should look like this:

    var ProductsView = Backbone.View.extend({
    
        events : {
            "click .filter-options-container" : "filterOptionContainerClick",
            "click .filter-options" : "filterOptionClick" // register sub-buttons' click handlers
        },
        initialize: function() {
            this.enabled = false; // state of the container click
        },
    
        filterOptionContainerClick: function(e){
            this.enabled = !this.enabled;
            if (this.enabled) $(e.currentTarget).addClass('active');
            else $(e.currentTarget).removeClass('active');
        },
    
        filterOptionClick: function(e){
            if (!this.enabled) return;
            $('.filter-option').removeClass('active');
            $(e.currentTarget).addClass('active');
            $('.filter-options-container').removeClass('active');
        }
    
    });