120

I'd like to be able to transition to a state and a pass an arbitrary object using ui-router.

I'm aware that usually $stateParams is used, but I believe this value is inserted into the URL, and I don't want users to be able to bookmark this data.

I'd like to do something like this.

$state.transitionTo('newState', {myObj: {foo: 'bar'}});

function myCtrl($stateParams) {
   console.log($stateParams.myObj); // -> {foo: 'bar'}
};

Is there a way to do this without encoding values into the URL?

Flip
  • 6,233
  • 7
  • 46
  • 75
eddiec
  • 7,608
  • 5
  • 34
  • 36
  • 1
    ui-router mechanisms preserve URL states across navigation. Thus, if an user refreshes the page, he comes back to the page he was in. If you don't want to use this behaviour, consider using other mecanisms (raw functions in your controller/directives, etc), and use cookies/storage for storing temporary data – Neozaru Dec 17 '13 at 11:02
  • Use localStorage with the url as the key for your data maybe? – Neil Apr 04 '14 at 20:19
  • 2
    Where do the values come from? Ui.router has the concept of a "resolve" to load data onto a scope before transitioning to the requested state. Similarly there are onEnter and onExit methods. In addition, you could use local storage. – Josh C. Jun 13 '14 at 02:08
  • As @JoshC. mentioned, sounds like you may want to look into resolving data before moving to a state. https://github.com/angular-ui/ui-router/wiki#resolve – TrazeK Aug 06 '14 at 23:48
  • See stackOverlord's answer as how to do it officially. – AlikElzin-kilaka Jun 03 '15 at 11:30

6 Answers6

164

In version 0.2.13, You should be able to pass objects into $state.go,

$state.go('myState', {myParam: {some: 'thing'}})

$stateProvider.state('myState', {
                url: '/myState/{myParam:json}',
                params: {myParam: null}, ...

and then access the parameter in your controller.

$stateParams.myParam //should be {some: 'thing'}

myParam will not show up in the URL.

Source:

See the comment by christopherthielen https://github.com/angular-ui/ui-router/issues/983, reproduced here for convenience:

christopherthielen: Yes, this should be working now in 0.2.13.

.state('foo', { url: '/foo/:param1?param2', params: { param3: null } // null is the default value });

$state.go('foo', { param1: 'bar', param2: 'baz', param3: { id: 35, name: 'what' } });

$stateParams in 'foo' is now { param1: 'bar', param2: 'baz', param3: { id: 35, name: 'what' } }

url is /foo/bar?param2=baz.

Ryan Langton
  • 6,294
  • 15
  • 53
  • 103
stackOverlord
  • 5,342
  • 6
  • 28
  • 29
  • Works with `transitionTo` as well. – AlikElzin-kilaka Jun 03 '15 at 11:29
  • 13
    I must be doing something wrong :-/ I'm on 0.2.13 but if I attempt to pass and object it comes out the in the state as the string `[object Object]` – ErichBSchulz Oct 02 '15 at 03:16
  • 15
    @ErichBSchulz Though it's not included in this answer, the trick to making this work is including the parameter name in the state's URL string and specifying the type as JSON. ex. `$stateProvider.state('myState', { url: '/myState/{myParam:json}', params: {myParam: null},...` See the [0.2.13 release notes](https://github.com/angular-ui/ui-router/releases/tag/0.2.13) and the code comments for this feature. – Syon Feb 02 '16 at 15:44
  • 1
    I had an id param in my URL and had to add that to the params object as well. `{ url: '/mystate/{id:[0-9]+}', params: { id: null, myParam: null }, ...` – GraehamF Mar 30 '16 at 21:32
  • Somebody needs to buy @Syon a beer! – Rahul Jaswa Aug 31 '16 at 01:34
  • 4
    There must be some black magic at play - my whole json is showing the the url :((( – Kabachok Jul 14 '17 at 11:46
  • 1
    @stackOverlord its working fine but the data that im passing in myParam is showing in the url too! which i dont want. – Tk1993 Jul 22 '18 at 18:52
25

There are two parts of this problem

1) using a parameter that would not alter an url (using params property):

$stateProvider
    .state('login', {
        params: [
            'toStateName',
            'toParamsJson'
        ],
        templateUrl: 'partials/login/Login.html'
    })

2) passing an object as parameter: Well, there is no direct way how to do it now, as every parameter is converted to string (EDIT: since 0.2.13, this is no longer true - you can use objects directly), but you can workaround it by creating the string on your own

toParamsJson = JSON.stringify(toStateParams);

and in target controller deserialize the object again

originalParams = JSON.parse($stateParams.toParamsJson);
Svatopluk Ledl
  • 316
  • 3
  • 6
21

Actually you can do this.

$state.go("state-name", {param-name: param-value}, {location: false, inherit: false});

This is the official documentation about options in state.go

Everything is described there and as you can see this is the way to be done.

Felipe Miosso
  • 7,309
  • 6
  • 44
  • 55
Tek
  • 1,178
  • 1
  • 12
  • 22
  • I tried this exact code and the object is not preserved. – Virmundi Oct 31 '14 at 18:37
  • 1
    you can't pass objects you can only pass single parameter values.... yo make it as an object you must put all of the properties as different url parameters. Angular-ui-router devs are still working on passing whole object. Actually that guys Svatopluk Ledl gave a nice solution. Just make the object as a whole json string and after that parse it. :) – Tek Nov 01 '14 at 19:25
13

Btw you can also use the ui-sref attribute in your templates to pass objects

ui-sref="myState({ myParam: myObject })"
Rob
  • 5,353
  • 33
  • 34
  • 1
    How do we receive this object in .state – Shubham Apr 12 '16 at 14:47
  • @Shubham you would configure the 'params' for the state which will receive the object, then using $stateParams to retrieve that object. see the doc http://angular-ui.github.io/ui-router/site/#/api/ui.router.state.$stateProvider for detail. – tao May 16 '16 at 15:29
  • this works but cannot keeping the data after page refreshing. – tao May 16 '16 at 15:34
9

1)

$stateProvider
        .state('app.example1', {
                url: '/example',
                views: {
                    'menuContent': {
                        templateUrl: 'templates/example.html',
                        controller: 'ExampleCtrl'
                    }
                }
            })
            .state('app.example2', {
                url: '/example2/:object',
                views: {
                    'menuContent': {
                        templateUrl: 'templates/example2.html',
                        controller: 'Example2Ctrl'
                    }
                }
            })

2)

.controller('ExampleCtrl', function ($state, $scope, UserService) {


        $scope.goExample2 = function (obj) {

            $state.go("app.example2", {object: JSON.stringify(obj)});
        }

    })
    .controller('Example2Ctrl', function ($state, $scope, $stateParams) {

        console.log(JSON.parse($state.params.object));


    })
vrbsm
  • 1,188
  • 15
  • 22
3

No, the URL will always be updated when params are passed to transitionTo.

This happens on state.js:698 in ui-router.

afternoon
  • 1,285
  • 16
  • 25