Protected page does not get destroyed, therefore ionViewCanEnter is not triggered after initial visit

I am using ionic-angular:3.9.2 and I really struggle to understand the logic behind the lifecycle events in combination with protecting pages, even though I digged into the Ionic sources on github.

I have a protected page, which is displayed in Tabs. Whenever an unauthorized user tries to access that page, I’d like to redirect him (on the root controller) to the login page. If he navigates back using the back button in the header, the first tab is selected on ionViewDidEnter and the home screen is displayed to the user. Needs more custom code than expected, but so far so good.

However, if the user navigates to the protected page another time ionViewCanEnter is not triggered anymore. I expected the page to be destroyed, since it is not on any stack, but this does not happen. I guess that’s the reason why ionViewCanEnter is not triggered again.

This is how my page looks like:

@IonicPage({
  name: 'MyProtectedPage'
})
@Component({
  selector: 'my-protected-page',
  templateUrl: 'protected.page.html'
})
export class MyProtectedPage implements OnInit, OnDestroy {

  constructor(private navCtrl: NavController) {
    console.log('page constructor');
  }

  ionViewCanEnter() {
    console.log('can enter');
    // push the login page on the root controller, so that login page is displayed without the tab bar
    this.navCtrl.parent.parent.push(LOGIN_PAGE_NAME);
    return false;
  }

  ionViewWillLeave() {
    console.log('will leave');
  }

  ngOnDestroy(): void {
    console.log('page destroy');
  }

  ngOnInit(): void {
    console.log('page init');
  }

}

The view stacks look like this:

  1. User opens app:
n4: [TabsPage]
--tabs, selected:  0
---- t0-0: [HomePage]
---- t0-1: []
---- t0-2: []
---- t0-3: []
  1. user is redirected to login
n4: [TabsPage, LoginPage]
--tabs, selected:  2
---- t0-0: [HomePage]
---- t0-1: []
---- t0-2: []
---- t0-3: []
  1. user clicks on the back button
n4: [TabsPage]
--tabs, selected:  0
---- t0-0: [HomePage]
---- t0-1: []
---- t0-2: []
---- t0-3: []

I cannot really use ionViewCanEnter due to various reasons.
Am I misunderstanding something?

If I pop a page explicitly, the IonicPage gets destroyed, but if it never becomes member of any stack I have no way to kill it? Not even manually?

Well, I don’t really fully understand what you are saying, but ionViewCanEnter should only return a boolean and have no navigation side effects like a navCtrl push.

Whether the user can see stuff on a tabs page can be build as logic inside the protected page.

Its also a matter of good UI on what you would like to present your user when he/she tries to do something he/she is not allowed to. So where do you put that logic?

I would try to build something without using the angular lifecycle hooks (ngOnInit and ngOnDestroy). That will only cause confusion

the code is simplified. in real it returns a promise, which is resolved to either true or false, depending on whether the user is logged in or not. the angular lifecycle hooks are not used, i just wanted to check if the component is destroyed.

i don’t really understand how that should work out. there’s no other page on the stack, so if i just return false, without navigating the user to some other page nothing will be displayed.

i think the easiest way is to redirect him/her to the login screen and actually i think that’s a very common scenario.

Maybe only make the tab visible when the user is logged in. Connecting a page that may not exist to a tab seems like a headache to me.

1 Like

This would solve the problem, but I prefer to show all the tabs to the user so that he/she is able to see what’s available without registering, provided that he/she is able to identify all the icons of course.

Then just change the string that is the name of the page pointed to by the tab. tab5Root = ‘SecretPage’ or tab5Root = ‘LoginPage’ based on whether the user is logged in.

Just thought about the same thing. I think i’ll go for that. I’m not too sure if this solves all issues in all use cases, but it should work for the Tabs.

Only downside is the user will see the tabbar, and not the login page only, but I guess I have to live with that.

Ionic is going to Angular routing in Ionic 4, so a lot of the weird things about guards will be gone. If you aren’t going to publish for a while, you might want to work on other pieces, and revisit page guards in Ionic 4.

Thanks for the hint and your help!