123

I am using AngularJS v1.2.0-rc.2 with ui-router v0.2.0. I want to pass the referrer state to another state so I use the toParams of $state.go like so:

$state.go('toState', {referer: $state.current.name});

According to the docs, this should populate the $stateParams on the toState controller, but it is undefined. What am I missing?

I've created a plunk to demonstrate:

http://plnkr.co/edit/ywEcG1

Rishabh
  • 3,752
  • 4
  • 47
  • 74
gwhn
  • 2,723
  • 4
  • 23
  • 26

14 Answers14

148

If you want to pass non-URL state, then you must not use url when setting up your state. I found the answer on a PR and did some monkeying around to better understand.

$stateProvider.state('toState', {
  templateUrl:'wokka.html',
  controller:'stateController',
  params: {
    'referer': 'some default', 
    'param2': 'some default', 
    'etc': 'some default'
  }
});

Then you can navigate to it like so:

$state.go('toState', { 'referer':'jimbob', 'param2':37, 'etc':'bluebell' });

Or:

var result = { referer:'jimbob', param2:37, etc:'bluebell' };
$state.go('toState', result);

And in HTML thusly:

<a ui-sref="toState(thingy)" class="list-group-item" ng-repeat="thingy in thingies">{{ thingy.referer }}</a>

This use case is completely uncovered in the documentation, but I think it's a powerful means on transitioning state without using URLs.

adamdport
  • 11,687
  • 14
  • 69
  • 91
bbrown
  • 6,370
  • 5
  • 37
  • 43
  • 2
    NOTE: (on v0.2.10) If the state is a child state of a parent that has a URL parameter, then that parameter needs to be included in the `params` array. – ivarni Jul 28 '14 at 11:02
  • 5
    I was getting an error saying "Missing required parameter" when I listed the params as an array in the state definition. Instead, list them as a hash like `{referer: true, param2: true, etc: true}` – Dave Ceddia Sep 30 '14 at 19:02
  • 1
    This didn't work for me in the latest v0.2.13. Perhaps, it was undocumented for a reason. – demisx Mar 23 '15 at 16:14
  • 1
    In the latest, you need to change params to be an object. so **params : { myParam : { value: _defaultValue/undefined_} }** – rbnzdave Aug 05 '15 at 23:45
  • Are you getting all of the properties of thingy? I am only getting one property back. I am referencing the html tag approach. I cannot get all of the properties back. – Winnemucca Aug 29 '15 at 00:08
  • where does`thingies` come from here? I am missing how to use it in the template file – Tash Pemhiwa Nov 19 '15 at 08:44
  • `thingies` is an array of objects that match the properties of the `params` object you want to pass to the new state. In the examples above, this `$state.go('toState', result);` is equal to this `ui-sref="toState(thingy)"` – bbrown Nov 20 '15 at 20:25
  • This shoud be default answer – Javasick Feb 26 '16 at 09:38
  • I found this statement to be untrue: "If you want to pass non-URL state, then you must not use url when setting up your state." I successfully passed `toParams` via `$state.go()`, I just had to define the `params` property of the state correctly, and was able to keep the `url` property just fine. – Chris Aug 10 '16 at 21:17
  • 2
    how can I get the data in the controller? – Shailendra Madda Aug 27 '16 at 13:22
  • "you must not use url when setting up your state" -> FALSE: See Answer here by @mbokil – cellepo Aug 29 '17 at 21:32
47

The Nathan Matthews's solution did not work for me but it is totally correct but there is little point to reaching a workaround:

The key point is: Type of defined parameters and toParamas of $state.go should be same array or object on both sides of state transition.

For example when you define a params in a state as follows you means params is array because of using "[]":

$stateProvider
.state('home', {
    templateUrl: 'home',
    controller:  'homeController'
})
.state('view', {
    templateUrl: 'overview',
    params:      ['index', 'anotherKey'],
    controller:  'overviewController'
})

So also you should pass toParams as array like this:

params = { 'index': 123, 'anotherKey': 'This is a test' }
paramsArr = (val for key, val of params)
$state.go('view', paramsArr)

And you can access them via $stateParams as array like this:

app.controller('overviewController', function($scope, $stateParams) {
    var index = $stateParams[0];
    var anotherKey = $stateParams[1];
});

Better solution is using object instead of array in both sides:

$stateProvider
.state('home', {
    templateUrl: 'home',
    controller:  'homeController'
})
.state('view', {
    templateUrl: 'overview',
    params:      {'index': null, 'anotherKey': null},
    controller:  'overviewController'
})

I replaced [] with {} in params definition. For passing toParams to $state.go also you should using object instead of array:

$state.go('view', { 'index': 123, 'anotherKey': 'This is a test' })

then you can access them via $stateParams easily:

app.controller('overviewController', function($scope, $stateParams) {
    var index = $stateParams.index;
    var anotherKey = $stateParams.anotherKey;
});
Jason McTaggart
  • 878
  • 1
  • 7
  • 18
Reza Rahimi
  • 958
  • 11
  • 16
  • Definitely it works and I have used it in my project. Did you test it? Let me know the problem, if you test it. – Reza Rahimi Nov 03 '14 at 10:35
  • 1
    it's not an object format {'index', 'anotherKey'} how can this work ? I did try it. It didn't work. – maxisam Nov 03 '14 at 15:25
  • Put your code snippet, version or something that can help to solving the problem. I have used these versions: AngularJS v1.2.26 , ui-router v0.2.11, CoffeeScript also I have used bower's version of them. – Reza Rahimi Nov 06 '14 at 07:55
  • 3
    this works, however replacing `params: {'index', 'anotherKey'},` with `params: {'index' : 'dummy', 'anotherKey' : 'dummy'},` otherwise it's not a valid javascript object – ps0604 Dec 19 '14 at 19:21
28

All I had to do was add a parameter to the url state definition like so

url: '/toState?referer'

Doh!

gwhn
  • 2,723
  • 4
  • 23
  • 26
  • The only way I can get this to work with `/toState/:referer` syntax is to use `$location.path()` instead of `$state.go()`. – nshew13 Feb 24 '14 at 17:58
  • You didn't find any other solution using ui-router's functionality? – Jason Apr 25 '14 at 20:05
  • there is a way to get this to work with $state.go(). Took me some time to get it right. See my example here. – mbokil Jan 12 '16 at 16:43
  • It worked. However it may not be clear what if you want to pass two parameters; so the following line does the trick. url: "/contacts?myParam1&myParam2" – eduardo92 May 03 '18 at 23:15
15

Not sure if it will work with AngularJS v1.2.0-rc.2 with ui-router v0.2.0. I have tested this solution on AngularJS v1.3.14 with ui-router v0.2.13.

I just realize that is not necessary to pass the parameter in the URL as gwhn recommends.

Just add your parameters with a default value on your state definition. Your state can still have an Url value.

$stateProvider.state('state1', {
    url : '/url',
    templateUrl : "new.html",
    controller : 'TestController',
    params: {new_param: null}
});

and add the param to $state.go()

$state.go('state1',{new_param: "Going places!"});
Phyxius
  • 161
  • 1
  • 6
  • As documented here: [Using Parameters without Specifying Them in State URLs](https://github.com/angular-ui/ui-router/wiki/url-routing#using-parameters-without-specifying-them-in-state-urls) – ricca May 18 '16 at 14:28
  • Coll... You saved my day men! Simple and direct solution. – Nowdeen Apr 01 '17 at 19:33
15

None of these examples on this page worked for me. This is what I used and it worked well. Some solutions said you cannot combine url with $state.go() but this is not true. The awkward thing is you must define the params for the url and also list the params. Both must be present. Tested on Angular 1.4.8 and UI Router 0.2.15.

In the state add your params to end of state and define the params:

url: 'view?index&anotherKey',
params: {'index': null, 'anotherKey': null}

In your controller your go statement will look like this:

$state.go('view', { 'index': 123, 'anotherKey': 'This is a test' });

Then to pull the params out and use them in your new state's controller (don't forget to pass in $stateParams to your controller function):

var index = $stateParams.index;
var anotherKey = $stateParams.anotherKey;
console.log(anotherKey); //it works!
mbokil
  • 3,202
  • 30
  • 22
11

In my case I tried with all the options given here, but no one was working properly (angular 1.3.13, ionic 1.0.0, angular-ui-router 0.2.13). The solution was:

.state('tab.friends', {
      url: '/friends/:param1/:param2',
      views: {
        'tab-friends': {
          templateUrl: 'templates/tab-friends.html',
          controller: 'FriendsCtrl'
        }
      }
    })

and in the state.go:

$state.go('tab.friends', {param1 : val1, param2 : val2});

Cheers

Cris R
  • 1,339
  • 15
  • 27
  • This worked fine for me, provided the controller reverences the param with the same name, so $stateParams.param1 for example. – nuander Jul 20 '15 at 19:17
  • yes @nuander , I forgot to mention about how to access that variable, thanks for that! – Cris R Jul 21 '15 at 07:03
8

I've spent a good deal of time fighting with Ionic / Angular's $state & $stateParams;

To utilize $state.go() and $stateParams you must have certain things setup and other parameters must not be present.

In my app.config() I've included $stateProvider and defined within it several states:

$stateProvider
    .state('home', {
        templateUrl: 'home',
        controller:  'homeController'
    })
    .state('view', {
        templateUrl: 'overview',
        params:      ['index', 'anotherKey'],
        controller:  'overviewController'
    })

The params key is especially important. As well, notice there are NO url keys present... utilizing stateParams and URLs do NOT mix. They are mutually exclusive to each other.

In the $state.go() call, define it as such:

$state.go('view', { 'index': 123, 'anotherKey': 'This is a test' })

The index and anotherKey $stateParams variables will ONLY be populated if they are first listed in the $stateController params defining key.

Within the controller, include $stateParams as illustrated:

app.controller('overviewController', function($scope, $stateParams) {
    var index = $stateParams.index;
    var anotherKey = $stateParams.anotherKey;
});

The passed variables should be available!

  • Can the value be a JSON object ? Like $state.go('view', { 'editObj': {val1:2, val2:3, val4:'Hello'}}). Because this isnt working for me. – PavanSandeep May 11 '15 at 15:17
6

Try With reload: true?

Couldn't figure out what was going on for the longest time -- turns out I was fooling myself. If you're certain that things are written correctly and you will to use the same state, try reload: true:

.state('status.item', {
    url: '/:id',
    views: {...}
}

$state.go('status.item', { id: $scope.id }, { reload: true });

Hope this saves you time!

Cody
  • 9,785
  • 4
  • 61
  • 46
6

I'd faced a similar problem. I ended up with a working solution after a lot of googling and trial and test. Here is my solution which would work for you.

I have two controllers - searchBoxController and stateResultController and a parameter named searchQuery to be passed from a view having a search box to a view showing the results fetched from a remote server. This is how you do it:

Below is the controller from which you call the next view using $state.go()

.controller('searchBoxController', function ($scope, $state) {
        $scope.doSearch = function(){
            var searchInputRaw = $scope.searchQueryInput;
            $state.go('app.searchResults', { searchQuery: searchInput });
        }
    })

Below is the state that would be called when the $state.go() gets executed:

.state('app.searchResults', 
            {
                url: '/searchResults',
                views:
                {
                    'menuContent': { templateUrl: 'templates/searchResult.html', controller: 'stateResultController' }
                },
                params: 
                {
                    'searchQuery': ''
                }
            })

And finally, the controller associated with the app.searchResults state:

.controller('stateResultController', function ($scope, $state, $stateParams, $http) {
        $scope.searchQueryInput = $stateParams.searchQuery;
    });
  • 1
    This worked for me and it was exactly what I needed, as I didn't want to pass the param in the URL but needed the url property in the state declaration. – Ernani Apr 03 '20 at 13:50
3

And in my case of a parent/child state. all the parameters declared in child state has to be known by the parent state

        .state('full', {
            url: '/full',
            templateUrl: 'js/content/templates/FullReadView.html',
            params: { opmlFeed:null, source:null },
            controller: 'FullReadCtrl'
        })
        .state('full.readFeed', {
            url: '/readFeed',
            views: {
                'full': {
                    templateUrl: 'js/content/templates/ReadFeedView.html',
                    params: { opmlFeed:null, source:null },
                    controller: 'ReadFeedCtrl'
                }
            }
        })
zinking
  • 5,561
  • 5
  • 49
  • 81
2

The solution we came to having a state that took 2 parameters was changing:

.state('somestate', {
  url: '/somestate',
  views: {...}
}

to

.state('somestate', {
  url: '/somestate?id=:&sub=:',
  views: {...}
}
Seth Caldwell
  • 179
  • 2
  • 5
1

Your define following in router.js

$stateProvider.state('users', {
    url: '/users',
    controller: 'UsersCtrl',
    params: {
        obj: null
    }
})

Your controller need add $stateParams.

function UserCtrl($stateParams) {
    console.log($stateParams);
}

You can send an object by parameter as follows.

$state.go('users', {obj:yourObj});
MahmutKarali
  • 339
  • 4
  • 8
1

I was trying to Navigate from Page 1 to 2, and I had to pass some data as well.

In my router.js, I added params name and age :

.state('page2', {
          url: '/vehicle/:source',
          params: {name: null, age: null},
.................

In Page1, onClick of next button :

$state.go("page2", {name: 'Ron', age: '20'});

In Page2, I could access those params :

$stateParams.name
$stateParams.age
Praveesh P
  • 1,399
  • 2
  • 25
  • 42
0

If this is a query parameter that you want to pass like this: /toState?referer=current_user

then you need to describe your state like this:

$stateProvider.state('toState', {
  url:'toState?referer',
  views:{'...'}
});

source: https://github.com/angular-ui/ui-router/wiki/URL-Routing#query-parameters

lgx
  • 590
  • 4
  • 9