2

I used this answer to get started with setting the title of my application dynamically. One solution worked nearly perfectly, except in one case. The following is my router:

app.config(['$routeProvider', function($routeProvider) {
        $routeProvider.when('/', {
            templateUrl: '/partials/home.html',
            controller: 'home',
            title: "Corvid"
        })
        .when('/archive', {
            templateUrl: "/partials/archive/all.html",
            controller: "archive",
            title: "Archive"
        }).
        when('/archive/:id', {
            templateUrl: "/partials/archive/one.html",
            controller: "article",
            title: ""
        })
        .otherwise({
            templateUrl: "/partials/errors/404.html",
            title: "Something went wrong!"
        });
    }
]);

app.run(['$location', '$rootScope', 
    function($location, $rootScope) {
        $rootScope.$on('$routeChangeSuccess', function(event, current, previous) {
            $rootScope.title = current.$$route.title;
        });
    }
]);

When using pre-defined and concrete strings, like "Corvid", it will work perfectly well enough. However, for the case of /archive/:id, I want something more arbitrary; the title of the article. That is to say, #/archive/2/ would set the title to Breaking news; corvid sucks at angular.js. Here is my factory for article:

services.factory('Article', ['$resource', function($resource) {
        return $resource('/api/v1/articles/:articleId', {}, {
            query: { method: 'GET', params: { articleId: '' } }
        });
    }
]);

So when I grab one of these articles, I want the title attribute to be whatever the title attribute is of that resource

Community
  • 1
  • 1
corvid
  • 10,733
  • 11
  • 61
  • 130
  • 1
    inject your factory called Article in routeChangeSuccess and grab your title returned by factory and assign to it $rootScope.title variable... – micronyks Jan 13 '15 at 19:08

2 Answers2

3

You could change your title property into a method, as follows:

app.config(['$routeProvider', function($routeProvider) {
        $routeProvider.when('/', {
            templateUrl: '/partials/home.html',
            controller: 'home',
            title: function () { return "Corvid"; }
        })
        .when('/archive', {
            templateUrl: "/partials/archive/all.html",
            controller: "archive",
            title: function () { return "Archive"; }
        }).
        when('/archive/:id', {
            templateUrl: "/partials/archive/one.html",
            controller: "article",
            title: function (Article) { return Article.get(this.id).title; }
        })
        .otherwise({
            templateUrl: "/partials/errors/404.html",
            title: function () { return "Something went wrong!"; }
        });
    }
]);

Then call it later, and pass the injected Article service.

app.run(['$location', '$rootScope', 'Article',
    function($location, $rootScope, Article) {
        $rootScope.$on('$routeChangeSuccess', function(event, current, previous) {
            $rootScope.title = current.$$route.title(Article);
        });
    }
]);
Chris Bouchard
  • 806
  • 7
  • 12
1

I think you would be best of using resolve in your route. You can use it to get the article from your service and set the title at the same time. Example of using resolve:

resolve = {
    article: ['$route', 'Service', function($route, Service) {
        var id = $route.current.params.id;
        return Service.get({'id': id}).$promise.then(function(article) {
            $route.current.$$route.title = article.id;
            return article;
        });
    }]
}

Now you don't have to fetch the article in your controller, you can simply inject article and at the same time you've set the title property in your route so your routechangehandler will simply work as expected.

From the API docs:

resolve - {Object.=} - An optional map of dependencies which should be injected into the controller. If any of these dependencies are promises, the router will wait for them all to be resolved or one to be rejected before the controller is instantiated. If all the promises are resolved successfully, the values of the resolved promises are injected and $routeChangeSuccess event is fired.

See https://docs.angularjs.org/api/ngRoute/provider/$routeProvider

iH8
  • 27,722
  • 4
  • 67
  • 76