$state.go isn't refreshing my view

I’ve got an app I’m developing that follows this user flow:

User is presented with a list of “things” and can use a button to create a new “thing”. On saving their new “thing”, the user should be taken back to the list of “things”, which should refresh and show their new “thing” in the list.

All the data is pulled down from and saved to a REST service.

Some code:

.state('app.list', {
  url: '/list',
  views: {
    'menu-view': {
      templateUrl: 'templates/list.html',
      controller: 'MyListCtrl',
      resolve: {
        objects: function(ObjectService) {
          return ObjectService.list();
        }
      }
    }
  }
})


.controller('ObjectsCtrl', ['$scope', 'objects', 'ObjectService', function($scope, objects, ObjectService) {

  $scope.objects = objects.results;

}])
.controller('MyListCtrl', ['$scope', '$rootScope', '$state', 'ObjectService', function($scope, $rootScope, $state, ObjectService) {

  // Called when the form is submitted
  $scope.createObject = function() {

    ObjectService.save( objectParams ).then(function(response) {
      $state.go('app.list', null, {reload: true});
    })
  };
  
})

What currently happens is that their “thing” is created and they are taken back to the list but the list has not refreshed.

Some observations:

  • It doesn’t matter if I use $state.go or $state.transitionTo, the result is the same.
  • The “resolve” on the app.list state does run when returning to the list. Further, checking the REST call, the expected number of results is being returned. They’re just not on the list.
  • I have a separate “refresh” method for the Pull to Refresh action which manually calls the service method and updates the $scope but I’d rather not have to pepper my code with this function.

I think the problem seems to be that while the resolve on the ui-router runs, the controller doesn’t get a chance to update the $scope. Is there a way of forcing that?

I’m very confused - can you tell?! :smiley:

1 Like

It looks like the issue is ui-router not reloading the controller when we use $state.go.

Try this to see if it fixes it:

$state.transitionTo('app.list, null, {reload: true, notify:true});

it could also be the default ionic caching. poor design decision IMO unless most people just don’t make data-driven apps? to disable, set this in an angular.module.config

$ionicConfigProvider.views.maxCache(0);
9 Likes

Just some information on cached views:

  • Cached Views:
  • Previously, as a user navigated an app, each exiting view’s element and scope would be destroyed. If the same view was accessed again then the app would have to recreate the element. Views can now be cached to improve performance.
  • Now, when a view is exited, its elements are left in the DOM, and its scope is disconnected from the cycle. When navigating to a view which is already cached, its scope is reconnected, and the existing element which was left in the DOM becomes the active view.
  • This also allows for scroll position of previous views to be maintained (without skippy jumps).
  • Config variables can be used to disable view caching, IE set to 0, or change the maximum number of views to cache.
  • Individual ionViews can disable caching by using the cache-view=“false” attribute, or from its $stateProvider.state config.
  • Note: Views with many large images or videos should not be cached.
  • The ionNavView docs have more further documentation.

If you don’t want to disable caching, but want specific code to be called each time a view is entered, you can use this in your controller:

$scope.$on('$ionicView.enter', function() {
    // code to run each time view is entered
});
9 Likes

No change with the addition of notify unfortunately.

That cracked it - I’ve disabled caching for that view. I may look into running a specific piece of code when entering the view, if I can figure out a way of telling the app where I came from but for now, the remove cache fix has worked perfectly.

Thanks!

1 Like

Brilliant !

I had exactly this same issue, and setting cache-view=“false” on my ‘parent view’ fixed it.

So this is indeed the recipe:

  • redirect back to the parent state with “reload = true” in the $state.go() call to make sure the Resolve function on the (abstract) parent state gets re-executed

  • set cache-view=“false” on the parent view so that the Controller gets re-instantiated (reinitialized) so that it picks up the new value provided by the Resolve

Both are necessary parts of the solution!

2 Likes

Does it work for nested state?

parent state is an abstract state say app.
child is app.home with cache:false … say app.home

Now when I do $state.go(‘app.home’, null, {reload:true}) from some other child app.profile, it doesn’t execute the code inside parent app controller. How do I make this work?

Yeah I’m not surprised that it doesn’t execute the parent controller, probably that’s by design.

Can’t you define a Route Resolve on the parent state? So you put the code to be executed in the route resolve instead of in the parent controller. No sure if that will work but it might.

[quote=“juice, post:3, topic:19845”]
$ionicConfigProvider.views.maxCache(0);
[/quote] Thanks, Juice you just saved my life :slight_smile:

This is by far the best solution if you have a data-driven application like I have. Almost every view makes an HTTP request and sometime the old data is still there, the controller isn’t refreshed when I enter again the same view. So I was trying to bypass that with $on.scope functions, but it wasn’t always functioning inside the Android app and if you have a big app, it’s not a practical solution to overload it with $on.scope functions.

I found on Toptal some great tips for Ionic development and the Common mistake #4 explains it pretty much:
Most Common Ionic Development Mistakes

$state.reload() does not reload the page. To refresh the template view page use:
$window.location.reload();

1 Like

I tried many experiments for refreshing view in Ionic Frame 1.3
In ionic frame Refreshing view is difficult. Because of Logging data or Data Reload etc…

I have make function That is $scope.doRefresh().

After someone do action ( etc upload action, data read action ), call doRefresh function.
And This view will be changed. Not necessary $state.go like webpage ^^,

I think ionicframe is mvc model. Change controll and will be view page.

$scope.doRefresh = function(){
// Call Data ( you want to change )
}

as mentioned by @juice and @brandyshea, we need to $ionicConfigProvider.views.maxCache(0); to allow ionic to execute the controller every time you come on the page by $state.go;

Well Consider a login form… I logged in and my dashboard is visible. I click logout. I get the same view i.e. To clear the data I tried
$scope.$on(’$ionicView.enter’, function() {
$scope.data = {} // considering my login form was data object.
});

It enters this block and hits that line in debugger. But on logging out, it still has the same prefilled view.

user “juice” provided answered worked for me but how do I tackel this situation without disabling caching?

I have same problem from last 10 days. my state changes , url in browser displaying proper but view is not refreshing displaying another file with same structure.

i want to reload my DOM my ionic view whenever user come on page. so my currect view displays.

that answer solved many issues for me.
thanx :+1:

I had a more complicated but simular problem:
wanted to go from “app.profile” to “app.home”, with backView disabled, and reload the home data if the the old view is profile

  //app.profile    
    $ionicHistory.nextViewOptions({
      disableBack: true
    }); // disable navback in next view
    $state.go('app.home');
    $rootScope.$emit('refr');

  //app.home    
   $rootScope.$on('refr', function() {
       $scope.doRefresh(); // load data from $http
   });

i could use $scope.$on(’$ionicView.enter’, function() ) and test $ionicHistory.backView(), but since i’m disabeling backview, it return null, so i created an event in the $rootScope

Hi, I am facing the weird situation. I can reinitialize my controller on same page but the data stored in service are lost. With $state.go controller is not reinitialising but service data is not lost and vice versa

Disable cache in state

cache: false

Disable cache in view

cache-view=“false”

check this video http://www.codeandyou.com/2017/08/how-to-refresh-view-in-ionic.html

1 Like

Thank you! worked to me