Type: feat
Platform: all
I have an app that needs a login to see personal informations.
Since ionic beta 14 and the introduction of Cached Views I have big trouble when a user logoff and login with a different user.
The new user after the login still see the cached views of the previous user.
At the moment it seems that the only solution to avoid this is to disable everywhere the cached views ( $ionicConfigProvider.views.maxCache(0);
).
It would be very useful to have a ionic.flushCachedViews() method to clear all the cached views.
I would call this when a user logoff.
Ok, sorry I just realised $ionicHistory.clearCache();
.
But I'm not able to work with it.
When I try to use it strange things happen to my app.
I'm still playing with this.
Very often when I try to use:
$ionicConfigProvider.views.maxCache(0);
$ionicHistory.clearCache();
cache: false,
(inside tab
abstract state)I have the following error:
0 874666 error Error: Attempted to assign to readonly property.
ChildScope@http://192.168.1.100:8100/lib/ionic/js/ionic.bundle.js:21459:42
$new@http://192.168.1.100:8100/lib/ionic/js/ionic.bundle.js:21467:40
compositeLinkFn@http://192.168.1.100:8100/lib/ionic/js/ionic.bundle.js:14866:38
compositeLinkFn@http://192.168.1.100:8100/lib/ionic/js/ionic.bundle.js:14890:24
nodeLinkFn@http://192.168.1.100:8100/lib/ionic/js/ionic.bundle.js:15526:35
compositeLinkFn@http://192.168.1.100:8100/lib/ionic/js/ionic.bundle.js:14887:23
publicLinkFn@http://192.168.1.100:8100/lib/ionic/js/ionic.bundle.js:14766:45
appendViewElement@http://192.168.1.100:8100/lib/ionic/js/ionic.bundle.js:47324:11
render@http://192.168.1.100:8100/lib/ionic/js/ionic.bundle.js:45864:58
init@http://192.168.1.100:8100/lib/ionic/js/ionic.bundle.js:45784:26
render@http://192.168.1.100:8100/lib/ionic/js/ionic.bundle.js:47225:18
register@http://192.168.1.100:8100/lib/ionic/js/ionic.bundle.js:47181:16
updateView@http://192.168.1.100:8100/lib/ionic/js/ionic.bundle.js:50834:31
http://192.168.1.100:8100/lib/ionic/js/ionic.bundle.js:50811:21
$broadcast@http://192.168.1.100:8100/lib/ionic/js/ionic.bundle.js:22496:33
http://192.168.1.100:8100/lib/ionic/js/ionic.bundle.js:39883:32
processQueue@http://192.168.1.100:8100/lib/ionic/js/ionic.bundle.js:20962:29
http://192.168.1.100:8100/lib/ionic/js/ionic.bundle.js:20978:39
$eval@http://192.168.1.100:8100/lib/ionic/js/ionic.bundle.js:22178:28
$digest@http://192.168.1.100:8100/lib/ionic/js/ionic.bundle.js:21994:36
$apply@http://192.168.1.100:8100/lib/ionic/js/ionic.bundle.js:22282:31
done@http://192.168.1.100:8100/lib/ionic/js/ionic.bundle.js:17439:53
completeRequest@http://192.168.1.100:8100/lib/ionic/js/ionic.bundle.js:17629:15
requestLoaded@http://192.168.1.100:8100/lib/ionic/js/ionic.bundle.js:17570:24
@gio82 I encountered the same issue, but was able to disable cache with one of below 2 ways instead of entire app from $ionicConfigProvider
. Thanks to @sreekanth on the ionic forum. http://forum.ionicframework.com/t/issues-w-routing-state-go/9418/15?u=acveer
Disable cache within state provider:
$stateProvider.state('myState', {
cache: false,
url : '/myUrl',
templateUrl : 'my-template.html'
})
Disable cache with an attribute:
ion-view cache-view="false" view-title="Home">Home
note: purposefully omitted '<' & '>' in the above HTML as the comment section is trying to render it.
Yeah, I ended up with the same solution but I consider this a turnaround.
All my views are now not cached. :(
I hope and guess driftyco will work to fix these bugs.
Thanks @acveer for your help.
I really need something like this.
$ionicHistory.clearCache()
should remove all cached views, this method doesn't touch in the previous view, this is unexpected in my opinion. I need a method to remove all the cached view's content programatically, would be very useful.
+1: Cached views are awesome, just need a way to clear them all on logout.
+1
clearCache should empty all the cached views, no matter where they stand or what is the parent state.
I will add some of my observations.
Would someone be able to reproduce this error using the nightly build? Thanks
+1
Looks good to me. For me, the error no longer occurs.
@adamdbradley okay, I spent the day at reducing my project to get a mcve that could help you guys. I'm not sure I really succeeded in this, but I did reduced it enough to demonstrate some of the issues clearly. I modified the names and all this, but it's close to the actual structure of my real project. I think it's a common pattern - there is a list of events, in each event there is a list of users, and each user has its own page.
Codepen - http://codepen.io/JerryBels/pen/ogEdaK
Now, you can easily see some bugs here, if I'm not mistaken. First, when selecting a user, and then coming back and selecting another, it does display the first user's page. That shouldn't be the case since it uses stateParams. Note that the bug must be somewhat linked to the multiple nested states, since I failed to reproduce it on a simple states architecture (but I'm still very young with Angular so I will let you guys figure it out).
Second, when displaying the menu and switching event (clearing the cache happens there), the first time you do that it's the previous event that displays again (you can see its name in the menu). The next tries are good.
I think that's not everything but it's all I could get with this simplified example. I really hope it will help you guys.
Good luck ! :-)
+1
+100
$ionicHistory.clearCache()
does not work
Forget my last comment, $ionicHistory.clearCache()
does work in the beta 14, nightly 995
I don't think so. The bugs demonstrated in my codepen above still occurs. Lets say it does work sometimes.
+100
still present. tested with v1.0.0-rc.0-nightly-1122.
is a workaround available?
https://github.com/angular/angular.js/issues/9128
looks like the same bug
Sorry everyone, but I'm not being provided with an example of it not working. I just reviewed the codepen and clear cache is working when fired from $ionicView.enter event. I'll need a detailed codepen, and detailed description showing exactly how it's not working, and a full description of what elements should be removed.
@adamdbradley - in the codepen I provided ( http://codepen.io/JerryBels/pen/ogEdaK ) the first "switch event" doesn't work, the cache is not cleared, the same event shows up. I added a title for it to be more visible. This is a clearcache bug.
Besides, even if it's not a clearcache bug, it's a huge cache bug that when you get to a user page it doesn't take its id (which is a state parameter) into account, showing the page of the user who was first opened because that page is cached ! Should I create another thread for this issue to be taken into account ?
/#/app/guests
Details like this help me to debug. With you're app, please describe in detail how to see what you're seeing, and what I'm looking for.
Note: You're not using lifecycle events, so controller logic is only going to fire once, which is what you're seeing in your profileCtrl. But I think the biggest issue is that the app.profile
state is set as an abstract state, which confuses the app and routing and a lot of its logic is skipped over.
Okay @adamdbradley, sorry :)
So, steps 1 to 4 are good...
To be completely honest, I have much more problems with cache on my real app but have a hard time minimizing it to a mcve while keeping the bugs, so I stopped when I observed this bug. Maybe solving it will solve the rest.
As of the abstract state, I thought I was forced to use it, since the doc ( https://github.com/angular-ui/ui-router/wiki/Nested-States-%26-Nested-Views#abstract-states ) says it's usefull to fulfill my use case ( "insert a template with its own ui-view(s) that its child states will populate", $scope and resolved dependencies inheritance...) but it looks like the same state without being stated as abstract does exactly the same thing... And then the cache does work well. Did I misunderstood what abstract is good for ? Also, when disabling the cache completely, it works even when stated as abstract without any issue.
@adamdbradley following your message about abstract not being usefull, I just took every abstract state off, as well as users concept. Here is the minimized codepen : http://codepen.io/anon/pen/Joxdeb
Now the clear cache fails all the time, which demonstrate much better the issue (I still feel it's linked to nested states). To reproduce simply :
I hope that helps to resolve the issue !
+1. $ionicHistory.clearCache()
doesn't work for me. Situation:
I have to set cache: false
in the profile page for it to work, which isn't ideal because I still want the cache to work until user logs out.
Would be great if $ionicHistory.clearCache()
just clears everything. Will be a useful action when logging out and logging in as a different user because data of most pages will change.
Version: Ionic 1.0 RC1
@buunguyen I fixed it by creating a state that only check if the user is logged in
or logged out
, just like this:
$ionicHistory.clearCache()
and $ionicHistory.clearHistory()
inside $ionicView.enter
The main problem with $ionicHistory.clearCache()
is that this method doesn't remove the previous view. So, if the previous view is the checklogin view, the profile view is correctly removed from the DOM.
History stack is like a array ['view 0', 'view 1', 'view 2']
, in this case, it's ['login', 'checklogin', 'profile']
, clearCache will keep the indices 0 and 1 (1 is the back view) and remove indices 2+
But there's differences by using clearCache
when $ionicView.enter
, $ionicView.afterLeave
, for example, when I log out a user, if I run clearCache()
inside $ionicView.afterLeave
it seems to correctly remove the back view from the DOM.
This is related to http://forum.ionicframework.com/t/clearcache-possible-bug/16532
@felquis can you post a Codepen example, please?
@felquis thank you for the tips. What I actually did was moving the clearCache()
call from post-logout to post-login and it appears to work, probably because my login view is before all others in the stack.
Thanks for the commit guys, I will test it and feedback whenever it's included into ionic.bundle.js.
Hi guys,
I have the same problem. $ionicConfigProvider.views.maxCache(0); resolving my problem but its a turnaround, because in my case some views can be cached, just i must clear the cache at a moment precise. $ionicHistory.clearCache() works now ? because isn't working for me :(
Steps :
$ionicHistory.clearCache() doesn't work for me on ionic 1.1.0
.
It would be great for this to work because I would like cached views, but I can't have cached views if I expect more than one person logging in and out of the app. With a cached view, the second user will see information from the first user.
Hi @eroh92. I'm facing the same problem. $ionicHistory.clearCache() not working in 1.1.0 and when the user logouts I have to manually delete the user data for each view. Really weird.
+1 here does not work
$ionicHistory.clearCache();
$ionicHistory.clearHistory();
$ionicHistory.clearCache() did not work for me either. Timeouting a call to $ionicHistory.clearCache() resolved the problem:
$timeout(function(){
$ionicHistory.clearCache();
}, 300);
Tested, still get cached views.
Yep, I'm also seeing this on v1.1.0.
Wrapping it in a $timeout doesn't work either, nor does using the promise version.
@jordidiaz, how are you clearing this for each view? The docs don't mention that you can pass in a state?
Hi @darshanrampatel
To clear view data (for example, has mentioned by @eroh92) I listen to a 'logout' event and clear the data in the event callback function. It's a manual work but if I don't do that the previous user's data is shown to the just logged user.
If someone has a better method, I'll be very thankful.
i also have this issue
in my signInCtrl:
$scope.$on('$ionicView.beforeEnter', function (e) {
$scope.hideBottom.hide = true;
console.log($ionicHistory.currentStateName());
console.log($ionicHistory.currentView());
$ionicHistory.clearCache();
});
not working
function dosignin(item){
$ionicHistory.clearCache().then(function(){
authService.doSignin(vm.userInfo).then(function(data){
console.log('controller then ---------------------');
console.log(data);
if(data.code == 'ACK'){
$state.go('main.expenses');
};
});
})
}
its working for me when i add the function in the doSignin FUNC
but not perfect
cacheView also appear in shortTime when i forward to state('main.expenses')
and this also help me in my signoutCtrl
authService.doSignout().then(function(result){
if(result.code == 'ACK'){
$timeout(function () {
$ionicHistory.clearCache();
$ionicHistory.clearHistory();
console.log('clearing cache');
},300)
hideSheet();
$state.go('app.signin');
}
})
also not perfect for me
and how to clear the factory data when i logout
Thanks to @mousenine , wrapping with a timeout works for me too (seems it just need to be on the same digest, so no need to set a number of ms).
$timeout(function() {
$ionicHistory.clearCache();
$ionicHistory.clearHistory();
});
This one works for me
$ionicHistory.clearCache().then(function() {
$state.go('...');
});
None of the above solutions worked for me and I tried all of them over a span of a few hours. :(
@sargismarkosyan gave the solution indeed, I found out the same. Waiting for the promise to resolve before navigating to the next state works perfectly.
I apologise for jumping in on a closed topic but here's something for those who this is not working for.
Have you considered that the issue might be that you are storing certain data in a global variable or within a service/factory rather than the issue being that Ionic is not clearing the cache?
This happened to me. Like everyone else, I was trying to blame it on Ionic and the clearing of cached views not working but the issue was because I wasn't clearing a global variable that was storing my data.
That, said, to ensure the clearing of cache works in Ionic, from my experience like others above, putting the clear cache function in a $timeout is the only way I was able to get it to work:
$timeout(function() {
$ionicHistory.clearCache();
$ionicHistory.clearHistory();
}, 100);
Something to notice is that since 1.1.0 release, clearCache() returns a promise called when cache is flushed. Didn't test it myself, but it seems to be the clean way to do it.
By docs it must return promise, but it doesn't.
Cannot read property 'then' of undefined
So, almost year is gone and there is no answer to question "How to clear cache".
@SergeyKuzmich there have been a number of answers to the problem, and yes, the function does return a promise:
There's a high chance this service is being used incorrectly, or the issue is coming from somewhere else (including user code). However, since this comment has gotten a lot of questions over the last year, it's clear this function is causing some confusion and/or is buggy.
To help us fix this, can anyone confirm this is still happening in a recent version of Ionic? I'm testing some of the code pens and not really seeing any issues with nightly/1.1.1.
Any other recent test cases will help us figure out what's going on.
Okay, noticing a few things here. First, you need to call clearCache
after the $ionicView.enter
lifecycle. However, it also needs to wait one digest step after, since we won't know the old view is not the active view until after. In the short term, use this code:
$scope.$on('$ionicView.enter', function() {
$timeout(function() {
$ionicHistory.clearCache();
});
});
We will look to a better solution. Some WIP: https://github.com/driftyco/ionic/tree/2939-view-events
Just landed in master: 06ef682a24822ded111d57d54f856fe5525befc9
With this fix, this code will work to clear any cached views behind the view that just entered:
$scope.$on('$ionicView.enter', function() {
$ionicHistory.clearCache()
});
Will work. Mind giving master a try and letting me know if it resolves your issues?
@mlynch thanks for your response
I've got a little different use case of clear cache. I've got feed of some data, by clicking to each item of data you see description of item and there is 'delete item' button. After pressing it item must be removed and user goes to feed screen and I need to refresh feed screen (reset cached view) and completely reload feed, because deleting one item can delete others connected items. So I need to clear cache after some action.
I've tried to use $ionicView.afterLeave event but nothing is changed, also I tried to use $timeout function - it is better but it did not clear cache for view I go and clear cache for others.
So,
$scope.$on('$ionicView.afterLeave', function() {
$ionicHistory.clearCache()
});
$state.go('feed');
doesn't work, and
$timeout(function() {
$ionicHistory.clearCache()
}, 100);
$state.go('feed');
works only if I have middle step such as
$timeout(function() {
$ionicHistory.clearCache()
}, 100);
$state.go('middle');
and in the 'middle' call $state.go('feed')
I'm working with private business app and not sure can I show it in CodePen or not. I've tried to repeat behavior in CodePen to show what I want to get.
could u please provide codepen example without using factory,
just using controller.
Thanks
The code provided by @mlynch is working for me:
$scope.$on('$ionicView.enter', function() {
$ionicHistory.clearCache()
});
it must be placed after the logout, in my case in the welcome controller
This is what I use during logout
// After logging out, ensure hitting back button from login screen doesn't return to the account settings page
$ionicHistory.nextViewOptions({
historyRoot: true,
disableBack: true,
});
$ionicHistory.clearCache().then(function () {
$ionicHistory.clearHistory();
});
Works for me
i am using bellow code but not entering in block to show alert.
$ionicHistory.clearCache().then(function () {
alert();
$ionicHistory.clearHistory();
});
This woked for me
$timeout(function(){
$ionicHistory.clearCache();
}, 500);
$state.go('app.login');
can any body solve my issue ?
my issue are that , i am installing another apk in my android phone but before of this an app installed (Build in ionic using angular with vs2015) by me, then i am try to install another one but its
unable to install.
This worked for me.
ionic --version
says 1.7.5
$ionicHistory.clearCache([$state.current.name]).then(function() {
$state.reload();
});
Well this is an old issue, but for anyone that's coming 2017 or later I will explain what really happens and how to solve it:
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(
E.g:
$ionicHistory.clearCache(['login', 'map', 'home']);
I cannot belive any Ionic developer didnt dug into the code before, or missed this simple datail.
I Hope someone takes advantage of this, even being so late.
UPDATE: 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:
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 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.
Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.
Most helpful comment
This worked for me.
ionic --version
says 1.7.5