0

I wonder what's the best way to configure a route which only purpose is to make use of a service call and then redirect.

I'm currently using this hack:

$routeProvider.when('/talks', { 
    template: '<div></div>', 
    controller: ['dateService', '$location', function(dateService, $location){
        var nextTalk = dateService.getNextTalkDate();
        $location.path('talks/' + nextTalk.format('MM') + '/' + nextTalk.format('YYYY'));
    }]
});

Currently I set the controller configuration to an inline controller implementation which has dependencies on the services and then does it's thing and redirects.

However, it feels a bit weird, since I have to set template to some dummy value because otherwise the controller would not be invoked at all.

It feels as if I'm stressing the controller property for something it wasn't intended for.

I guess there should be a way to run some view unrelated code that has access to services on a route. I could right my own $routeProvider I guess but that seems to be a bit heavy for something I would consider should be built in.

Christoph
  • 26,519
  • 28
  • 95
  • 133

2 Answers2

1

Looks like '/talks' is a kinda abstract since its just used to redirect to other routes.. So how about setting up a route like this:

''/talks/:month/:year'

Where :month and :year is optional. If no month or year is given, your service returns a default talk. Which is probably the next talk. If params are given you just fetch the requested data.

So there's no redirect required. Now you specifiy the controller and the needed view and expose your data on the scope. Optionally would it be better to wrap your service call in a promise and resolve it at routeProviders resolve property.

This makes sure that the view only change if everything's resolved fine.

Hope that helps!

Christoph
  • 26,519
  • 28
  • 95
  • 133
Pascal Precht
  • 8,803
  • 7
  • 41
  • 53
  • Ah, yes, that sounds like a viable solution :) Thanks – Christoph Mar 31 '13 at 22:35
  • Mmmh...it seems there is no way to make the parameters optional: http://stackoverflow.com/a/12807157/288703 so if you just hit `/talks` it doesn't catch the route – Christoph Mar 31 '13 at 22:48
  • Ok, you can sorta have optional parameters when you define multiple routes pointing to the same controller. – Christoph Apr 01 '13 at 00:03
1

There's no way to inject services into anywhere into a route. Whether it be redirectTo or template, any code in there is handled on the module level. This means that the module is loaded first and then when the application has boostrapped itself then the services and injection-level code is executed. So the controller is your best bet (since that does support injection).

Controller is used in a lot of areas in AngularJS and it should work fine for what you're trying to do. You can either handle the redirection like you do in there or you can setup three different routes that point to the same controller (where you build the page).

var handler = { controller : 'Ctrl' };
$routeProvider.when('/talks', handler).
               when('/talks/:month, handler).
               when('/talks/:month/:year', handler);

And if you do end up using redirection, then just use $location.path(url).replace(). This will make the history stack jump back one level and therefore that the redirection triggering URL won't be in your history.

matsko
  • 21,895
  • 21
  • 102
  • 144
  • I will probably go with your solution and have two rules pointing to the same controller (that's basically like having optional parameter as Pascal suggested) I will just check for those parameters then and redirect from there. Thanks for the extra information about the history trick. That was also bugging me :) – Christoph Apr 01 '13 at 00:00