3

I don't understand how to share some sort of "singleton" application-state holding object model, between different views, using browserify. Books and tutorials often use a global namespace such as:

var app = app || {};

I have a simple example app which consists of:

app.js

var $ = require('jquery');
var Backbone = require('backbone');
Backbone.$ = $;

var MenuView = require('./views/MenuView');
var ContainerView = require('./views/ContainerView');

new MenuView();
new ContainerView();

MenuView.js

var Backbone = require('backbone');
var ApplicationState = require('../models/ApplicationState');

module.exports = Backbone.View.extend({
    el: '#menuView', 
    events: {
        'click .menuLink': 'changePage'
    },
    changePage: function(event) {
        event.preventDefault();
        var viewName = $(event.target).attr('data-view');
        ApplicationState.set('currentView',viewName);
    }
});

ContainerView.js

var Backbone = require('backbone');
var ApplicationState = require('../models/ApplicationState');

module.exports = Backbone.View.extend({
    el: '#containerView', 
    initialize: function() {
        this.listenTo( ApplicationState, 'change', this.render );   
        this.render();
    },
    render: function() {
        this.$el.html( ApplicationState.get('currentView') );
    },
    close: function() {
        this.stopListening();
    }
});

This seems working using this approach:

ApplicationState.js var Backbone = require('backbone');

var ApplicationState = Backbone.Model.extend({
    defaults: {
        currentView: 'TransactionListView'
    }
});

module.exports = new ApplicationState();

Is the ApplicationState module really created only once (caching) ? Or is there the risk of recreating / resetting the module?

What is the best practice for my use case? Thank you a lot.

2
  • I guess it is ok, you may check how many instances of ApplicationState will be created by adding console.count('Application State') within ApplicationState.js file and see output in console. Commented Aug 28, 2014 at 21:25
  • this.$el.html( ApplicationState.get('currentView') ); should probably be this.$el.html( ApplicationState.get('currentView').$el ); Commented Aug 29, 2014 at 2:46

1 Answer 1

5

Yes, there will only be one ApplicationState in the example you gave. Browserify executes anything following module.exports = as soon as the js file is run and then anything that requires that file is passed a reference to the result.

However it’s generally better practice to avoid sharing state this way between views and instead use a parent view that delegates to subviews. There are a number of ways to set this up. For ideas on best practices for organizing a backbone app, check out this talk: https://www.youtube.com/watch?v=Lm05e5sJaE8

For the example you gave I would highly consider using Backbone's Router. In your example you have a nav that changes the "main" view. Backbone.Router intercepts navigation and checks it against your specified routes calling your view method. For instance:

router.js

module.exports = Backbone.Router.extend({
    initialize: function(options){
        this.ContainerView = new ContainerView();
    },
    routes: {
        'transactions': 'showTransactionListView',
        'transaction/:id': 'showTransactionDetailView'
    },
    showTransactionListView: function() {
        this.ContainerView.render('TransactionListView');
    },
    showTransactionDetailView: function(id) {
        this.ContainerView.render('TransactionDetailView', id);
    }
});

Then any link to #transations (or just transactions if you're using Backbone History) will call your ContainerView.render('TransactionListView'). And, as a bonus, if you reload the page you'll still be looking at TransactionListView.

Other notes:

  • You'll want to make sure you discard old views when you replace them (by calling .remove() on them) so as to avoid memory leaks. Further Reading
  • You can add some flexibility to your router and use a controller pattern to render subviews with this nifty plugin
Sign up to request clarification or add additional context in comments.

2 Comments

Ok thank you very much, I'll take a look to the talk. Can you explain me how routers would fit in my example please? Thank you again!
Sure. I've updated my answer with a (minimal) router example.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.