Backbone and document.title
Asked Answered
V

5

16

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

Vodka answered 7/5, 2012 at 14:46 Comment(2)
Why do you need a View.title?.. I think View shouldn't be related to the page.title, I think the Router itself should overwrite the document.title without bother any other component of your application.Phonics
That is the way I have it at the moment, just wanted to avoid the repetitive code in the router. I thinking of binding a function in the router that get's a view's title and sets it as the document.title without having the repeat the line with each routeVodka
G
34

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.

Gird answered 8/5, 2012 at 10:25 Comment(2)
That's an interesting solution as well. I'd imagined cases (having built them) where the View is "activated", not initialized or re-rendered (maybe for example it's just hidden). So, I'd need to add an "activated" function/event to trigger. Also, due to composition, I wasn't sure if a View should know how it fits into the bigger picture (maybe it shouldn't be allowed to trigger the title change right now, etc.). Nonetheless, I like the pattern.Dicotyledon
Revisited this and implemented a global variable for the application. In it I store an event aggregator. An event will be triggered by the view and the aggregator will change the document title. As a side note an event can be created on the router to listen to any route changes. This can maybe trigger document.title change. stackoverflow.com/a/9521144Vodka
P
28

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

document.title = 'new title';
Procora answered 7/5, 2013 at 9:35 Comment(5)
... are you serious? C'mon, that's the most stupid thing I heard ever. jQuery is build on pure JS and, in fact, jQuery is a framework to build things with pure JS. So, what's the problem using pure JS???Procora
That is all correct (of course jquery is built using pure js!), but not what i said, it will always look cleaner if you stick to one or the other whenever you can.Belligerency
people lean on jQuery too much. to the point now where people who call themselves 'js developers' can't recall how to do DOM manipulation with native JavaScriptPenitent
Agreed with @miduga, always use pure JS over a library if it makes sense to do so. Your point regarding 'a mix' of conventions or styles (jquery vs native) is reasonably valid, but why ever use a library when you can do things in native, its unnecessary abstraction.Picky
The problem is you haven't understood the question. I'm quite sure the OP is aware HOW to change the title. His problem is, how to organize the code that changes the title while routing.Annoyance
D
2

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.

Dicotyledon answered 8/5, 2012 at 1:38 Comment(0)
W
1

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);
    }
  }

})
Wylen answered 18/12, 2013 at 4:33 Comment(0)
T
1

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!
Trammell answered 14/3, 2017 at 18:54 Comment(1)
Thanks for your input but switched to Angular since this post.Vodka

© 2022 - 2024 — McMap. All rights reserved.