27

I am fairly new to Backbone and have the following question:

I have a collection of models.

I have a collection view displaying tabs (with a view for each model in the collection).

I have a view for a model (for the content).

I have a router with routes.

What I am trying to achieve is a functionality like http://jqueryui.com/demos/tabs/

I click on a tab (model of collection) and then want to pass the model to the content view maybe change it and reflect the changes in the collection.

I came up with four solutions:

In the router:

'switchCommunity': function(id) {
        // (a) set new model attributes
        this.view.community.model.set(communities.get(id));

        // (b) replace model
        this.view.community.model = communities.get(id);

        // (c) a custom function of the view changes its model
        this.view.community.changeModel(communities.get(id));

        // (d) a new view
        this.view.community = new View({
            model: communities.get(id)
        })
}

The problem here is

  • (a) does not reflect changes to the model in the collection

  • (b) does not trigger (change) events, because the bind in the initialize function of the view never triggers, because it is a completly new model

  • (c) seems like a hack to me

  • (d) everytime i click on a tab a new view is created (is this a performance issue?)

What is the best pratice here?

Riebel
  • 789
  • 2
  • 10
  • 22
  • 2
    I would try (d) - this doesn't become a performance issue if you remove the old view first. – swatkins Dec 21 '11 at 15:27
  • in (d) I overwrite my this.view.community is this sufficient or do I have to remove it manually? – Riebel Dec 21 '11 at 15:32
  • 1
    This should be sufficient, as long as the old dom elements aren't hanging around and have event listeners bound to them, they should be garbage collected. I'd verify with firebug, but I think that's correct. – swatkins Dec 21 '11 at 15:34
  • I always add a close method to my views which removes it from the dom after unbinding all bacbone and dom events. – Sander Dec 21 '11 at 20:18
  • Thank you for this very useful question! Option (d) is also not a good option because if you have event listeners on your (sub)view, they will pile up when new (sub)views are created – CamelBlues Feb 28 '13 at 17:04

4 Answers4

16

One of your solution is close to be okay :D

Here is what you want:

this.view.community.model.set(communities.get(id).toJSON());

And this will trigger model.on("change") as well.

zsitro
  • 1,812
  • 3
  • 24
  • 34
8

Why do you think (c) is a hack? It seems like a good place to encapsulate the unbinding of the old model, and connecting up the new one.

Paul Hoenecke
  • 5,060
  • 1
  • 20
  • 20
1

The Backbone.Marionette plugin provides a streamlined solution for your problem.

It provides functionality for Application Initialization, View Management, and Event Aggregation.

In essence, it takes the pain out of hiding and showing multiple views.

You can read this blog post to learn more about it.

Paul
  • 18,349
  • 7
  • 49
  • 56
  • Absolutely, but keep in mind the plugin is fairly new and might change a few times in the not so distant future – Sander Dec 21 '11 at 20:20
0

The short answer is you should use d. Yes is isn't performant but unless you notice slowdown in the user interface you shouldn't worry too much. You should code something that 1. always works 2. doesn't take long to code so you can move on to coding other more important features.

If/when you need more performance then you can take the extra time to do c. To be the most performant you shouldn't destroy and re-render templates. You should use jquery to manually find the elements on the DOM and replace them with the new model. When you call:

view.$el = _.template(string, model); 

It's very little code but lots of work for the browser. Replacing the DOM with a new model is much more performant.

If you need to be more performant you can use object pooling. I've been working on a PerfView for backbone that implements a lot of optimizations. https://github.com/puppybits/BackboneJS-PerfView There's comments in the code with a lot of best practices to maintain the best browser performance.

puppybits
  • 1,110
  • 12
  • 16