jviotti
jviotti

Reputation: 18909

Code from multiple view instances causing conflicts

I'm porting a web service into a single-page webapp with Backbone. There is a basic layout consisting on a header, an empty div#content where I'm attaching the views and a footer.

Every route creates the corresponding view and attachtes it to div#content replacing the view that was rendered before with the new one.

I'm using require.js to load the backbone app and it's dependencies. All Backbone code is pretty small, only one file as I'm only using a router and a view. This AMD module depends on a util.js file exporting functions that are used in the views. After a view is created and rendered, It executes the utilities (jquery stuff, ajax, etc) it needs from util.js.

The problem is that when I render a view, it's utilities get called, and when I navigate to another route, and a new view is created, the new view's utilities are called now, but the older view's utilities are still running.

At some point, I have utilities from like five views running altogether, causing conflicts sometimes.

It's clear than my approach is not good enough, as I should have a way to stop/start utilities functions as some kind of services.

I'll paste relevant code that shows my current approach:

require(["utilities"], function(util) {
...
Application.view.template = Backbone.View.extend({
  el: "div#content",
  initialize: function(){
    this.render();
  }, 
  render: function(){
    var that = this;
    // ajax request to html
    getTemplate(this.options.template, {
      success: function(template) {
        var parsedTemplate = _.template( template, that.options.templateOptions || {});
        that.$el.html(parsedTemplate);
        // execute corresponding utilities
        if(that.options.onReady) {
          that.options.onReady();
        }
      },
      error: function(template) {
        that.$el.html(template);
      }
    })
  }
});
...
Application.router.on('route:requestPayment', function(actions) {  
  var params = { template: 'request-payment', onReady: util.requestPayment };
  var view = new Application.view.template(params);
});       
...

});

util.requestPayment consist of a function having all stuff needed to make template work.

I'm confused about how should I handle this issue. I hope I was clear, and any suggestions or help will be appreciated.

EDIT: utilities.js snippet:

...

var textareaCounter = function() {
  $('#requestMessage').bind('input propertychange', function() {
    var textarea_length = 40 - $(this).val().length;
    if(textarea_length === 40 || textarea_length < 0) {
      $('#message-counter').addClass('error').removeClass('valid');
      $("#submitForm").attr('disabled', 'disabled');
    }
    else if(textarea_length < 40 && textarea_length > 0) {
      $('#message-counter').removeClass('error');
      $("#submitForm").removeAttr('disabled');
    }
    $('#message-counter').text(textarea_length);
  });
}
...    
var utilities = utilities || {};
...
utilities.requestPayment = function() {      
  textareaCounter();
  initForm();
  preventCatching();
  requestPaymentCalcFallback();
};
...
return utilities;
...

Upvotes: 0

Views: 78

Answers (1)

neeebzz
neeebzz

Reputation: 11538

I would suggest that you should store reference to the currently active view somewhere in your app.

You create a new view here :

var view = new Application.view.template(params);

but you have no access to this variable afterwards. So it exists but you can't stop/delete/get rid of it.

What we normally do is to have a Parent App class which initializes the whole app and manages everything. Your every module in requirejs would be depenedent on it. When a new route is navigating, you ask the Parent App class to change the view. It will delete the old view, create a new one, populate div#content and then store the reference of it.

I think when you delete the old view, all the utilities will stop responding to it.

If you still have the issue with events being called, then you might need to use stopListening event binders before deleting the view reference.

Upvotes: 1

Related Questions