Seer
Seer

Reputation: 5237

Is it possible to clear the view cache in Ionic?

I'm currently working on a Angular/Ionic/Cordova project and we've recently upgraded to the latest Ionic beta. From the version the project was using before, this introduced the view cache. It has also however introduced an issue in doing so.

The application is customer-facing and is very data-centric. A user must authenticate to view data associated with their account, currently however; when a user logs out, and logs into another account, because the view(s) are still cached they are presented with the views of the last account.

The app should still cache the views when the user is logged in, as it helps make the app feel much quicker, but the cache should be purged when a user logs out.

Setting cache-view="false" is not an option, as it would completely disable the cache.

I've also tried setting $ionicConfig.views.maxCache(0); and then back to the default of 10 in the hopes that it would purge the cache in doing so, but it had no effect.

The last thing I can think of to do is fire an event when a user logs in that refreshes all data that's currently loaded into the views - however, this would take a bit more effort than I feel it should.

Is there a way to simply clear the view cache?

Upvotes: 45

Views: 75782

Answers (5)

Marco Silva
Marco Silva

Reputation: 574

Well this is an old issue, I will explain what really happens and how to solve it:

P.S: If you want to go straight to SOLUTION just scroll down right away.

The code of $ionicHistory.clearCache():

 `clearCache: function(stateIds) { return $timeout(function() { 
     $ionicNavViewDelegate._instances.forEach(function(instance) { 
         instance.clearCache(stateIds); 
     }); 
 }`

So, as you can see, it takes 1 parameter cllaed stateIds which is an array of stateId. Indeed i struggled to find out that stateId is nothing more than stateName.

So, let's go deeper. The code of $ionicNavView.clearCache which is used in the line above "instance.clearCache(stateIds)" is:

self.clearCache = function(stateIds) {
var viewElements = $element.children();
var viewElement, viewScope, x, l, y, eleIdentifier;

for (x = 0, l = viewElements.length; x < l; x++) {
  viewElement = viewElements.eq(x);

  if (stateIds) {
    eleIdentifier = viewElement.data(DATA_ELE_IDENTIFIER);

    for (y = 0; y < stateIds.length; y++) {
      if (eleIdentifier === stateIds[y]) {
        $ionicViewSwitcher.destroyViewEle(viewElement);
      }
    }
    continue;
  }

  if (navViewAttr(viewElement) == VIEW_STATUS_CACHED) {
    $ionicViewSwitcher.destroyViewEle(viewElement);

  } else if (navViewAttr(viewElement) == VIEW_STATUS_ACTIVE) {
    viewScope = viewElement.scope();
    viewScope && viewScope.$broadcast('$ionicView.clearCache');
  }

}
};

And as you can see in the code, this clearCache DOES NOT CLEAR ALL CACHES, instead, it destroy all cached views that matches a value in the stateIds array. If there's no parameter IT JUST DESTROY THE ACTUAL VIEW.

So the solution for this, using just the Ionic way is to call $ionicHistory.clearCache() with all your state names in an array as parameter.

E.g: SOLUTION $ionicHistory.clearCache(['login', 'map', 'home']); I cannot belive any Ionic developer didnt dug into the code before, or missed this simple datail. There's a lot of people who's aching for this.

Just to make it crystal clear, i want to point out where the bug itself is (if we can call it bug), maybe can be handy for devs:

self.clearCache = function(stateIds){

[...]

 var viewElements = $element.children();

} What the whole function does is basically:

Get all elements using JQLite Loop the elements Check if an element equals one in the StateIds array and destroy it; go to next element. Check if element in the loop is cached or active, and in both true cases destroy it I wont dig deeper into this but debugging it i could see that the elements gotten from var viewElements = $element.children(); is not an array of all your views content, not even the cached ones, intentionally or not it does not loop through out all your states to clear all those that matches 'ACTIVE' or 'CACHED'. If you want it to loop through ALL your states and destroy all cached views and data you need to explicity pass the stateIds array parameter.

Besides that there's another strange behavior, because when i was debugging it i saw when the var viewElements array was filled up with 2 elements, and these 2 elements were from the same state, one resolved to 'CACHED' another resolver to 'ACTIVE', even resolving to the 2 types used in the if conditions the cache was not cleared at all.

I personally think that this is somekind wrong implemented or is wide used wrongly. The fact is that there's a lot of people cracking their heads on this and devs don't even give this simple explanation.

Upvotes: 0

Nirav Gandhi
Nirav Gandhi

Reputation: 2005

I stumbled across a similar scenario where logging in with another user was showing me stale/cached view. You can do cache: false at the state definition level but that entirely disables cache for that state in your app.

What you can rather do is clear all the cached view and history when user enters the signin/login state of your application (as you said). Seems ideal.

// code inside your signin controller

$scope.$on("$ionicView.enter", function () {
   $ionicHistory.clearCache();
   $ionicHistory.clearHistory();
});

Upvotes: 22

user4227915
user4227915

Reputation:

You can also do it by setting cache:false in your $stateProvider:

$stateProvider.state('myState', {
   cache: false,
   url : '/myUrl',
   templateUrl : 'my-template.html'
})

Upvotes: 8

ABCD.ca
ABCD.ca

Reputation: 2495

In the state definition in app.js you can add cache:false to disable caching (See Disable cache within state provider in the Ionic docs. Or, you can keep caching except when you know data has changed.

  • If you're already on the page, you can do, $state.go($state.currentState, {}, {reload:true})
  • If you're on another state and want to go back to the state that is normally cached but you want it to be refreshed, you can do, $ionicHistory.clearCache().then(function(){ $state.go('app.fooState') })

Note, the latter requires clearCache to return a promise. See the changes I made in this pull request and compare the implementation of clearCache that you have now with mine: https://github.com/driftyco/ionic/pull/3724

Upvotes: 67

Andoni Mart&#237;n
Andoni Mart&#237;n

Reputation: 253

Are you searching for something like this?:

$ionicHistory.clearCache();

EDIT:

There is an issue in Ionic's github: Issue

Upvotes: 5

Related Questions