OmerGertel
OmerGertel

Reputation: 2583

Setting page title with ember.js

What is the best way to set the page's title, so that when transitioning between urls, the title will reflect the new state? Is there a way to set the Router to do this?

I want a method that allows me to set a page title schema for each state. So, if the route has parameters, they will be passed into the pageTitle:

sessions : Ember.Route.extend({
       route:"/sessions",
       connectOutlets : function(router) {
           //...
       },
       pageTitle:function(){
            return "Sessions";
       },
   })

I'm open to any suggestions as to how it is best to implement this type of functionality on the Model or someplace else.

Upvotes: 22

Views: 9970

Answers (7)

Quang Van
Quang Van

Reputation: 12095

I had the same question.

Note: That you can change the starting title by editting app/index.html

In lieu of a simple & blessed way (Ember devs are busy on more important things I'm sure), the answer I found most elegant was from CodeJack found here:

// file: app/helpers/head-title.js    

import Ember from 'ember';

export function headTitle(title) {
  Ember.$('head').find('title').text(title);
}

export default Ember.Helper.helper(headTitle);

now in any view template you can just add the helper

{{head-title 'View Header'}}

Editted: Updated code for Ember 2.0

source: Ember Handlebars Templates in <head> tag

Upvotes: 1

steveax
steveax

Reputation: 17743

After a long discussion on this pull request it was decided that this didn't belong in core. There is a component and ember-cli addon that implements the functionality.

Upvotes: 5

givanse
givanse

Reputation: 14943

A quick and dirty approach, in your routes:

actions: {
  didTransition: function() {
    Ember.$('title').text('My awesome page title');      
  }
}

Upvotes: 0

Milan Simek
Milan Simek

Reputation: 442

I used the following method with Ember 1.4.0:

App.PageTitle = Ember.Object.create({
    defaultTitle: 'This route has no title defined'
});

RouteWithTitle = Ember.Route.extend({
    activate: function() {
            if ('title' in this){
                document.title = this.title;
                App.PageTitle.set('title',this.title);
            }else{
                document.title = App.PageTitle.defaultTitle;
                App.PageTitle.set('title',this.title);
            }
    }
});

App.ExampleRoute = RouteWithTitle.extend({
    title: 'This is an example route'
});
App.AnotherRoute = RouteWithTitle.extend({
    title: 'This is another route'
});

(Similar to Micha Mazaheri's answer.)

You can define a title for each route using the title property. The page title will be automatically updated, and you can call the title in any handlebars template by using {{App.PageTitle.title}}

Upvotes: 4

Micha Mazaheri
Micha Mazaheri

Reputation: 3481

As I struggled a lot to figure out a nice pattern to setup the page title, with the lastest Ember.js (1.0.0 RC7), I decided to create a subclass of Ember.Route:

AppRoute = Ember.Route.extend({
    renderTemplate: function(controller, model) {
        this.render();

        var pageTitle = this.title ? this.title(controller, model) : null;
        document.title = pageTitle ? pageTitle : "Default Title";
    }
});

// all routes extend this new 'AppRoute'

App.PageRoute = AppRoute.extend({
    model: function(params) {
        // return your model
        return App.Page.find(params.page_id);
    },
    title: function(controller, model) {
        // return whatever should be your page title
        return controller.get('title');
    },
});

Probably this will be natively supported by Ember.js if this pull request is merged: Router now observes the 'title' property on route handlers and sets document.title. Note: this pull request doesn't seem to pass controller and model as parameters.

If you prefer the Coffee Script equivalent: Ember.js: An easy and clean way to set the page title.

Upvotes: 6

MilkyWayJoe
MilkyWayJoe

Reputation: 9092

The previous answer was applicable for an old version of Ember. After several changes the Framework has reached version 1.0 RC2 and it's close to be final, so I decided to update this answer.

As an example, please look into the Routes defined in this fiddle: http://jsfiddle.net/schawaska/dWcUp/

The idea is the same as the previous answer, just in a different way since the Routing API has changed considerably.

The Route below, uses the activate hook to set the title of the document via jQuery:

App.ProductRoute = Em.Route.extend({
    activate: function() {
        $(document).attr('title', 'Auto Web Shop - Product');
    }
});

Edit: As noted in the comment section:

FYI activate is the API method, rather than enterpauldechov


This answer was given in a previous version of Ember and it no longer applies.

Inside your connectOutlets you can do something as simple as using jQuery to modify the document's title attribute:

[...]
home: Em.Route.extend({
    route: '/',
    connectOutlets: function (router, context) {                
        // router.set('navbarController.selected', 'home');                     
        router.get('applicationController')
              .connectOutlet('home');                     

        $(document).attr('title', 'YOUR TITLE GOES HERE');
    }
}),                
[...]

But you'd have to do this for every route.

In case you have something like a navbar controller that sets the selected nav menu item, you watch the selected property to both bind the "active" or "selected" css class to the nav item and set the page title; or you could have a property just for the title on the navitem model that you'd pass through the context (but I believe you'd have to handle this in the view and transition to the route from there).

Anyway, this is just to show one of the possible ways to set the page title.

EDIT: I've modified an existing fiddle to do that. Take a look at the method navigateTo in the router: http://jsfiddle.net/schawaska/hEx84/ (to see it running go here http://jsfiddle.net/schawaska/hEx84/show/)

Upvotes: 19

Dwayne Forde
Dwayne Forde

Reputation: 1394

I took this approach:

Ember.Route.reopen({
    enter: function(router) { 
        this._super(router)

        # Set page title
        name = this.parentState.get('name')
        if (!Em.none(name)) {
            capitalizedName = name.charAt(0).toUpperCase() + name.slice(1)
            $(document).attr('title', "Website - " + capitalizedName)
        }
   }
})

A few issues came up with using navigateTo, this ended up being more reliable and cleaner for my situation at least.

Upvotes: 5

Related Questions