24

Get the context, angular, ui-router, nothing special, a root view built with 3 named ui-views. so in index.html we have

<body>
  <div ui-view='left'>
  <div ui-view='center'>
  <div ui-view='right'>
</body>

my route looks like

$stateProvider
 .state('main', {
  url: '/',
  views: {
   'left': {templateUrl: 'foo.html'},
   'center': {templateUrl: 'bar.html'},
   'right': {templateUrl: 'xyz.html'}
  }
 })
 .state('main.b', {
  url: '/b',
  params: { foo: {value: 'bar'} }
  views: { 'right@': {templateUrl: '123.html'} } // I wish to update $stateParams in 'left@' view
 })
 .state('main.c', {
  url: '/c',
  params: ...
  views: { 'left@': ..., 'center@': ..., 'right@': .. }
 });

Is there a way in going to b state to update the $stateParams in the 'center' and 'left' view?? I can get it using a service but i need to add a $watch to the variable I need and it looks a little bit hacky to me.

Going into c state I can actually get what I want, but the view is reloaded, and i wish to avoid this behaviour cause i have a canvas in the 'left' view.

3 Answers 3

33

You could use the following to go to a specific route without reloading the views:

$state.go('.', {parm1: 1}, {notify: false});

The last object literal represents the options which you can pass along to go. If you set notify to false, this will actually prevent the controllers from being reinitialized. The . at the beginning is the absolute state name or relative state path you wanna go to.

The important thing is the notify though.

Sign up to request clarification or add additional context in comments.

3 Comments

This somehow still causes all components in the view to $init and then immediately $destroy, which may lead to some serious performance issues. You can see if you add a console.log() to this.$onInit() and this.$onDestroy() within your components.
Controller is still re-instantiated using this method, $onInit is called.
Dynamic params is the way to go.
26

I think that using "Dynamic params" is now a better solution:

When dynamic is true, changes to the parameter value will not cause the state to be entered/exited. The resolves will not be re-fetched, nor will views be reloaded.

$stateProvider.state('search', {
   url: '/search?city&startDate&endDate',
   templateUrl: 'some/url/template.html',  
   params: {
      city: {
         value: 'Boston',
         dynamic: true
      }
   }
 }

and then:

$state.go('.', {city: 'London'});

https://ui-router.github.io/ng1/docs/latest/interfaces/params.paramdeclaration.html#dynamic https://github.com/angular-ui/ui-router/issues/2709

2 Comments

Thanks for the updated answer, but the question is how do we now differentiate between route changes caused by $state.go from your example (dynamic params) and somebody just going back by using the browser back button?
Thanks so much @julien-malige, I found any answer "all without dynamic tip" and when they spoke of dynamic, they had no example... your answer is complete! thanks!
11

Quoting @christopherthielen from https://github.com/angular-ui/ui-router/issues/1758#issuecomment-205060258:

using notify: false is almost never a good idea, and is now deprecated. Use reloadOnSearch if you must.

You can also try dynamic parameters in the 1.0 version (currently 1.0.0-alpha.3). In your state, configure a parameter as dynamic and implement the uiOnParamsChanged callback :

.state('foo', {
  url: '/:fooId',
  params: { fooId: { dynamic: true } },
  controller: function() {
    this.uiOnParamsChanged = function(changedParams, $transition$) {
      // do something with the changed params
      // you can inspect $transition$ to see the what triggered the dynamic params change.
    }
  }
});

For a demo, have a look at this plunker: http://plnkr.co/edit/T2scUAq0ljnZhPqkIshB?p=preview

2 Comments

Something that caught me off guard is that if you have views defined in the stateProvider definition, define your controller property in the views definition and not outside. Eg. in docs: ui-router.github.io/docs/latest/interfaces/… views: { header: { controller: function() { this.uiOnParamsChanged = function(changedParams, $transition$) { ... } }, templateUrl: "header.html" }, body: { controller: "bodyCtrl", templateUrl: "body.html" }, footer: "footerComponent" }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.