lexeme
lexeme

Reputation: 2973

subscriber (for a custom event) doesn't exist. backbone.js

There's HeaderView view in my application. According to what route has been fired the view gets a custom heading. The view's subscribed to headerview:titleChanged event.

headerview.js

var HeaderView = Backbone.View.extend({
    el: $('#header-region'),
    initialize: function() {
        bus.on('headerview:titleChanged', function(args) {
            this.setTitle(args.title);
        }, this);
        this.render();
    },
    setTitle: function(title) { this.$el.find('.title').html(title); },
    render: function() { return this; }
});

at router.js

var AppRouter = Backbone.Router.extend({
    initialize: function() { this.route('', 'defaultRoute'); }
});

// trying to create it before AppRouter even got initialized
new HeaderView();

var appRouter = new AppRouter();
appRouter.on('route:defaultRoute', function() { 
    _routeHandlers.renderDefaultContentRegion(); 
});

Backbone.history.start();

at router.js, _routeHandlers.renderDefaultContentRegion()

// trying to send message
bus.trigger('headerview:titleChanged', {title: 'heading text'});

The problem is that router gets created first and header view gets created next and as the result there's no headerview:titleChanged recipient.

Is it possible to render HeaderView before default route gets fired? How do I handle that?

Upvotes: 0

Views: 165

Answers (1)

mu is too short
mu is too short

Reputation: 434755

The HeaderView is presumably an essential part of the application so it should be created during application start up, the problem is getting the order right. You could hijack AppRouter#initialize to be your application constructor and let it create the HeaderView at the right time:

var AppRouter = Backbone.Router.extend({
    initialize: function() {
        this.route('', 'defaultRoute');
        new HeaderView();
        bus.trigger('headerview:titleChanged', {title: 'heading text'});
    }

Demo: http://jsfiddle.net/ambiguous/dpSbB/

Alternatively, you could move all the initialization into a separate application constructor and let that line things up in the right order. This also gives you a convenient place to put global things (such as your event bus) without worrying about polluting the global namespace. Something like this:

var AppRouter = Backbone.Router.extend({
    initialize: function() {
        this.route('', 'defaultRoute');
    },
    //...
});

var app = {
    bus: _({}).extend(Backbone.Events),
    initialize: function() {
        new HeaderView;
        new AppRouter;
        app.bus.trigger('headerview:titleChanged', {title: 'heading text'});
        Backbone.history.start();        
    }
};

app.initialize();

Demo: http://jsfiddle.net/ambiguous/eLyys/

Upvotes: 1

Related Questions