Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

$stateParams vs $transition$.params() #3237

Closed
jwickens opened this issue Dec 31, 2016 · 17 comments
Closed

$stateParams vs $transition$.params() #3237

jwickens opened this issue Dec 31, 2016 · 17 comments

Comments

@jwickens
Copy link

I was following https://ui-router.github.io/tutorial/ng1/hellosolarsystem and trying to get state params working. However, on trying to load a state with a resolve using $transition$ there was an unlogged error and nothing loaded.

I found in the hello universe docs @stateParams and that works fine.

What is the difference or do the docs need updating?

@NeoGenet1c
Copy link

Related question (that might get answered by answering @jwickens' question about the difference between those two):

What is the best practice to access parameters inside Services?

Sometimes, I find it very cumbersome to obtain $transition$ inside a service, but documentation clearly states that $stateParams service should NOT be used anymore.

Is $state.params better option?

@christopherthielen christopherthielen added this to the 1.0.0-final milestone Jan 11, 2017
@christopherthielen
Copy link
Contributor

christopherthielen commented Jan 11, 2017

I found in the hello universe docs $stateParams and that works fine.

do the docs need updating?

Yes, since $stateParams are deprecated, the tutorial needs to be updated. Thanks for noting this!

What is the difference

The difference is documented in the migration guide and in the $stateParams docs for 1.0.0-rc.1

The $stateParams that gets injected into routed controllers is the same as $transition$.params() which can be seen in the source code, where it is literally an alias for this.params().

@christopherthielen
Copy link
Contributor

christopherthielen commented Jan 11, 2017

@NeoGenet1c

What is the best practice to access parameters inside Services?

The $stateParams docs for 1.0.0-rc.1 give the suggested practice as follows:

inject $uiRouterGlobals and use UIRouterGlobals.params

(This is the same as injecting $uiRouter and accessing $uiRouter.globals.params)

@ashgibson
Copy link

I am trying to use $transition$ in my controller instead of $stateParams but get the following runtime error: Unknown provider: $transition$Provider <- $transition$.

I am using typescript with angular 1 and a webpack build with ng-annotate, my constructor code is below:

constructor(private $transition$: Transition) {
   'ngInject';
}

@christopherthielen
Copy link
Contributor

@theatrain check out https://ui-router.github.io/guide/ng1/route-to-component#accessing-transition

@ashgibson
Copy link

Perfect, that works. Thanks!

@harrylincoln
Copy link

@christopherthielen , I think I'm having a similar problem where I need a $stateParams reset for parent state when sharing a single controller in child states:

http://stackoverflow.com/questions/41860680/angular-ui-router-state-params-reset-for-parent-when-sharing-controller-in-chi

If you could advise as I've researched the hell out of it and running out of ideas!

@archasek
Copy link

@harrylincoln did you come up with something?

@harrylincoln
Copy link

harrylincoln commented Jan 31, 2017

Yes I did! Workaround that's a little messy but safe. I basically introduced an 'init' state that inits the detail states and have the parent just handle basic html templating stuff.

I answered my own question on stackoverflow:
http://stackoverflow.com/questions/41860680/angular-ui-router-state-params-reset-for-parent-when-sharing-controller-in-chi/41958537#41958537

@samiraguiar
Copy link

@christopherthielen was there any change to this? I'm using the legacy template style with Angular 1.2 and I get the provider error when injecting $transition$.

@harrylincoln
Copy link

@samiraguiar this may help:
#3309

@samiraguiar
Copy link

samiraguiar commented Jun 8, 2017

@harrylincoln Thanks, Harry, but I think my problem is different.
I have a directive defined as:

angular.module('app').directive('myDirective', function($transition$) {});

And my route defined as follows:

{
    name: 'someRoute',
    url: '/path/to/route',
    template: '<my-directive></my-directive>'
}

But this gives me the "Unknown provider: $transition$Provider <- $transition$" error.

Here's a plunker showing the problem.

What am I doing wrong?

@harrylincoln
Copy link

harrylincoln commented Jun 8, 2017

@samiraguiar pretty sure you've missed a step there. Your routing won't have access to your directives since it's bound to the app.config which (I believe) is instantiated before your directives/controllers.

Basically this won't work:

{
    name: 'someRoute',
    url: '/path/to/route',
    template: '<my-directive></my-directive>'
}

You need something like this:

  1. Make sure your app knows what your directive is when initing the app:
angular
    .module(app, ['ui.router', require('angular-sanitize'), require('angular-animate')])
    .service('someService', requiredService)
    .config(routesConfig)
    .directive('myDirective', require('./app/directives/myDirective')) ...
  1. Routing:
{
    name: 'someRoute',
    url: '/path/to/route',
    template: './template-that-uses-the-directive'
}
  1. HTML itself:
<div class="container">
<my-directive></my-directive>
</div>

This is all in the ui router docs

@samiraguiar
Copy link

samiraguiar commented Jun 8, 2017

@harrylincoln Thanks, Harry.

Indeed, apparently $transition$ is only injected as a local when constructing the route's controller, but not when constructing the controllers for any directive within the template.

Got it working by changing my directive code to:

angular.module('app').directive('myDirective', function($scope) {
    var id = $scope.$resolve.$transition$.param().id;
});

Though I don't find it pretty.

@harrylincoln
Copy link

Makes sense. There are many ways to skin a cat in Angular ;)

@christopherthielen
Copy link
Contributor

christopherthielen commented Jun 9, 2017

If you are routing to a directive template, bind the transition object as an attribute like so:

    template: '<my-directive trans="$resolve.$transition$"></my-directive>'

If you are using route-to-component, you can use an input binding

.component('myCmp', {
  bindings: { '$transition$': '<' }
  controller: function() {
    this.$onInit = () => {
      this.$transition$.params()
    }
  }
});

then route to component:

.state({
  name: 'someRoute',
  component: 'myCmp'
});

@stale
Copy link

stale bot commented Jan 24, 2020

This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs.

This does not mean that the issue is invalid. Valid issues
may be reopened.

Thank you for your contributions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants