Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Durandal.js 2.0 Set document title within activate method

Tags:

durandal

In my shell, I have set up my routes like so:

router.map([
            { route: '', title: 'Search', moduleId: 'viewmodels/search/search' },
            { route: 'location/:paramX/:paramY', title: 'Location', moduleId: 'viewmodels/location/location' }
        ]).buildNavigationModel();

I have an activate method like so:

activate: function(paramX, paramY) {
    // TODO: set document title
    // TODO: do something with input params    
}

For the location page, the document title is set to the Location | [Name of my app]. I would like to change this to be made up from the params taken in the activate method (paramX, paramY) on my activate method for the location page. How do I do this?

like image 791
user2269352 Avatar asked Sep 10 '13 08:09

user2269352


2 Answers

You can achieve this by overriding the default behaviour of the process of the router to set the title.

The title is always set after the navigation is complete so the activate method of your viewmodel has been called before. The current implementation in Durandal 2.0 is:

   router.updateDocumentTitle = function(instance, instruction) {
        if (instruction.config.title) {
            if (app.title) {
                document.title = instruction.config.title + " | " + app.title;
            } else {
                document.title = instruction.config.title;
            }
        } else if (app.title) {
            document.title = app.title;
        }
    };

This is called in the method completeNavigation in the router.js.

In instance param you have the ViewModel that you are activating so a possible solution could be to override the updateDocumentTilte function in shell.js or main.js and use the instance to get the values that you want. For example you could do something like this (make sure you have the app and the router instance):

 router.updateDocumentTitle = function (instance, instruction) {
            if (instance.setTitle)
                document.title = instance.setTitle();
            else if (instruction.config.title) {
                if (app.title) {
                    document.title = instruction.config.title + " | " + app.title;
                } else {
                    document.title = instruction.config.title;
                }
            } else if (app.title) {
                document.title = app.title;
            }
        };

In this code we check if the instance (the current ViewModel) contains a method setTitle, if it does then we get the title calling the function. Then in our viewmodel we can have something like:

define(function () {

var id;
var vm = {
    activate: function (param) {
        id = param;
        return true;
    },
    setTitle: function () {
        return 'My new Title ' + id;  //Or whatever you want to return
    }
};

return vm;
});

If your viewmodel does not contain this method, then it should fall to the current behaviour.

like image 148
margabit Avatar answered Sep 25 '22 21:09

margabit


Here's how I achieved it:

    activate: function (product, context) {
        // Update the title
        router.activeInstruction().config.title = "Buy " + product;
        ...
        ...
        ...
        ...

It works, but I don't know if that's the approved method.

like image 44
Sam Avatar answered Sep 24 '22 21:09

Sam