Solvedui router 1.0: Can't inject $transition$ into component's controller?

Trying to route to component, but the following throws an error: Unknown provider: $transition$Provider <- $transition$

.component('adminApplicants',{
    templateUrl:'admin.applicants.html',
    controller:function($http,$transition$){
    }
})

With legacy .controller("SomeCtrl",function($transition$){}), there is no error. Why?

22 Answers

✔️Accepted Answer

Yes, this is a limitation of route to component.

$transition$ isn't a global service, it's a locally scoped injectable. In old school .controller() style, ui-router actually instantiates the controller using $controller(yourControllerFunction) so we can pass locals to it (such as $transition$). With route-to-component, we no longer instantiate the controller ourselves. Instead, we generate a template string, such as <admin-applications></admin-applications> and let angular do its thing.

You can use component input bindings to address this:

.component('adminApplicants',{
    bindings: { $transition$: '<' },
    templateUrl:'admin.applicants.html',
    controller:function($http,$transition$){
    }
})

Now the generated template looks like this:
<admin-applications $transition$="::$resolve.$transition$"></admin-applications>

The $transition$ will be bound on your controller.

Keeping this ticket open because it needs to be added to the docs, here: https://github.com/ui-router/ui-router.github.io/blob/master/_guide/105.ng1-route-to-component.md

Other Answers:

To summarize this issue

  • You cannot inject $transition$ into a component controller's constructor when using route-to-component.
    • The $transition$ object is not a global service
    • The component is constructed by angular itself, so we cannot provide additional DI locals
  • You cannot rename the $transition$ to a different variable on the controller in the component's bindings.

Workarounds

  • You can bind $transition$ directly
    • .component('foo', { bindings: { $transition$: '<' } })
  • You can globally alias the $transition$ token yourself
    • $transitionsProvider.onBefore({}, trans => trans.addResolvable({ token: "trans", resolveFn: () => trans });
  • You can locally alias the $transition$ token yourself
    • $stateProvider.state({ ... resolve: { trans: '$transition$' } });
  • You can map your component input (blarble) to a specific resolve ($transition$) using ui-router component view bindings.
    • $stateProvider.state({ ... component: 'foo', bindings: { blarble: '$transition$' } });

Because a) injecting into the component is impossible and b) I have no control over renaming the binding and c) there are four workarounds, I am closing this issue as wontfix

This also applies to https://ui-router.github.io/docs/latest/modules/ng1.html#_stateparams where it says to inject $transition$ using $inject, which does not work as I get the same error as mentioned above. Also, the migration guide says to inject $transition$ as well. Or, is there something I'm missing?

More Issues: