Question

I'm creating a single page application with backbone.js and would like to know the best way to handle changing the title. I was thinking of having a 'title' option in the view and have the router (somehow) get set the document.title. Has anyone implemented anything similar? Thanks

Was it helpful?

Solution

why not use the evented nature of Backbone.js.

First off I don't think it's up to the Router to delegate the updating of the Document Title. Especially if you're working with larger client-side applications you want to keep it simple and make sure each part of your application fulfils a specific task.

The router is there to delegate routes, nothing more.

what I'd suggest instead is (depending on how you initialize your application) to create an application-level event aggregator.

var app = new Application();
app.eventAggregator = _.extend({}, Backbone.Events);

and bind an event to your app as such:

app.eventAggregator.on('domchange:title', this.onDomChangeTitle, this);

where in your Application construct

onDomChangeTitle: function (title) 
{
   $(document).attr('title', title);
}

and now, instead of having to leave it up to the Router to always grab the title and making sure there's getTitle method in each view, you can - inside your view and therefore, ANY view - trigger the following event when you render or initialize the view:

app.eventAggregator.trigger('domchange:title', this.title);

it makes for cleaner and leaner code in my opinion, but then again, that's just an opinion.

OTHER TIPS

Why are you all using jQuery to change the title of the document instead using pure Javascript? Faster, easier, cleaner...

document.title = 'new title';

I'd suggest just placing the code in your router callbacks. It will be another line of code, but without knowledge of the current view, the router/app won't know what view has the correct title. (There's really not a good place to override the behavior and provide a document title without replacing some built in functions in Backbone.JS).

You could add something to your view very simply:

var PeopleView = Backbone.View.extend({
    title: 'People are People',
    //
    //or 
    //
    getTitle: function () {
        return "Something Dynamic";
    }
});

And then in your router callback:

var v = new PeopleView();
$(document).attr('title', v.getTitle());

One other option would be to just have the View set it when it's created or when a special method is called. But, I'd use the first option.

This is what I do this my project:

var App = {};

App.HomeView = Backbone.View.extend({
  documentTitle: 'my site title'
})
var Router = Backbone.Router.extend({
  routes: {
      '':    'home'
    , 'home': 'home'

, baseTitle: ' - my site'

, home: function(actions) {
    var obj = this;
    obj._changePage('HomeView');
  }

, changeTitle: function(title, withoutBaseTitle) {
    var obj = this;

    if(withoutBaseTitle !== true)
      title += obj.baseTitle;

    document.title = title;
    return obj;
  }

, _changePage: function(viewName, viewOptions) {
    var obj = this;
    var page = App[viewName]();

    if(typeof page.documentTitle !== 'undefined') {
      obj.changeTitle(page.documentTitle);
    }
  }

})

Kinda very old post, but I'll give it one more reincarnation.


With current Marionette v3.2.0 you can do the following:

// Get title from view where we manage our layout/views
var viewTitle = view.triggerMethod('page:title');

In your view you creating that magic method like this:

Mn.View.extend({
    onPageTitle() {
        return ['User', this.model.get('id')].join(' | ');
    }
});

And a title resolution itself can be the following:

document.title = !!viewTitle
        ? (
            _.isArray(viewTitle)
                ? [baseTitle].concat(viewTitle)
                : [baseTitle, viewTitle]
          ).join(' / ')
        : baseTitle ;

Allows resolution of titles returned as arrays and implodes by a single separator

  • It can be easily integrated in application workflow in place where you manage your content shows.
  • onPageTitle will be called in context of view (this will be the view instance inside the function), what gives the possibility to invoke model data and any view related stuff.
  • No need to bother with checking method availability, just call-and-go.
  • Moreover, you can always fallback to default title if no such method is defined as triggerMethod will return undefined on such cases.
  • Profit!
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top