ionic-framework: [ionic 4] ionViewWillEnter only triggers once.

Bug Report

Ionic Info Run ionic info from a terminal/cmd prompt and paste the output below.

Ionic:

   ionic (Ionic CLI)          : 4.0.5
   Ionic Framework            : @ionic/angular 4.0.0-beta.3
   @angular-devkit/core       : 0.7.2
   @angular-devkit/schematics : 0.7.2
   @angular/cli               : 6.1.2
   @ionic/ng-toolkit          : 1.0.5
   @ionic/schematics-angular  : 1.0.4

Cordova:

   cordova (Cordova CLI) : 8.0.0
   Cordova Platforms     : android 7.0.0, ios 4.5.5

System:

   Android SDK Tools : 25.2.5
   ios-deploy        : 1.9.2
   ios-sim           : 6.1.2
   NodeJS            : v7.4.0 (/usr/local/bin/node)
   npm               : 4.0.5
   OS                : macOS High Sierra
   Xcode             : Xcode 9.4.1 Build version 9F2000

Environment:

   ANDROID_HOME : /usr/local/Cellar/android-sdk/24.4.1_1

Describe the Bug The ionViewWillEnter lifecycle (if its still called that) only triggers once. In ionic 3 the ionViewWillEnter triggered every time you navigated to the view. Now it only triggers the first time.

Steps to Reproduce Steps to reproduce the behavior:

  1. Add ionViewWillEnter to your view
public ionViewWillEnter(): void {
     console.log('hi');
}
  1. Navigate to the page
  2. Navigate to a different page
  3. Navigate again to the page with the ionViewWillEnter

Expected Behavior Expect the console.log('hi') to be logged every time I navigate to the view.

Additional Context Note that I use tabs. Is there perphaps a Angular lifecycle which replaced ionViewWillEnter?

-- tabs
     -- View 1 (with ionViewWillEnter)
     -- View 2

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 14
  • Comments: 48 (12 by maintainers)

Most upvoted comments

In the meanwhile, as a workaround, I am using below setup to mock the ionViewWillEnter event. Note that the url in the subscription should be that of the current page.

import { OnEnter } from '../on-enter';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Subscription } from 'rxjs/Subscription';
import { NavigationEnd, Router } from '@angular/router';

@Component({
    selector: 'app-home',
    templateUrl: 'home.page.html',
    styleUrls: ['home.page.scss'],
})
export class HomePage implements OnInit, OnEnter, OnDestroy {

    private subscription: Subscription;

    constructor(
        private router: Router
    ) { }

    public async ngOnInit(): Promise<void> {
        await this.onEnter();

        this.subscription = this.router.events.subscribe((event) => {
            if (event instanceof NavigationEnd && event.url === '/tabs/(home:home)') {
                this.onEnter();
            }
        });
    }

    public async onEnter(): Promise<void> {
        // do your on enter page stuff here
    }

    public ngOnDestroy(): void {
        this.subscription.unsubscribe();
    }
}

Custom interface

export interface OnEnter {
    onEnter(): Promise<void>;
}

Hi guys,

any thing on this from the Ionic team yet?

How is it a duplicate of #14566 ? You can have lifecycle hooks without lazy-loading. Lifecyle hooks are supposed to be about navigation and wich page/component is focused, not about how and when it is loaded.

I’m not talking from a technical point of view (I don’t know how Ionic handle it internally) but from a functionnal point of view.

It’s closed because it’s a duplciate of #14566 (it makes no sense to have different issues open for the same topic)

I’ve implemented the following more generic workaround:

import { OnDestroy } from '@angular/core';
import { Router, NavigationEnd, ActivatedRouteSnapshot, ActivatedRoute } from '@angular/router';
import { Subject } from 'rxjs';
import { takeUntil, filter, tap } from 'rxjs/operators';

export abstract class RouterPage implements OnDestroy {

    private ngUnsubscribe: Subject<void> = new Subject();

    constructor(router: Router, route: ActivatedRoute) {
        router.events.pipe(
            takeUntil(this.ngUnsubscribe),
            filter(event => event instanceof NavigationEnd),
            filter(_ => this._isComponentActive(
                router.routerState.snapshot.root.pathFromRoot,
                route.snapshot.component
            ))
        ).subscribe(_ => this.onEnter());
    }

    private _isComponentActive(path: ActivatedRouteSnapshot[], component: any): boolean {
        let isActive = false;
        path.forEach((ss: ActivatedRouteSnapshot) => {
            if (ss.component === component) {
                isActive = true;
            } else {
                isActive = this._isComponentActive(ss.children, component);
            }
        });
        return isActive;
    }

    abstract onEnter(): void;

    public ngOnDestroy(): void {
        this.ngUnsubscribe.next();
        this.ngUnsubscribe.complete();
    }
}

This class can then used as follows:

export class MyPage extends RouterPage implements OnDestroy {

    constructor(private router: Router, private route: ActivatedRoute) {
        super(router, route);
    }

    onEnter() {
        console.log('My page enter');
    }
   
   onDestroy() {
      super.ngOnDestroy();
   }

}

@paulstelzer Can you at least tell us if it’s planned to change the lifecycle behaviours for tabs ?

With your post medium (thanks for the clarification btw) the current behaviour is not a bug. But at the same time it’s not really the behaviour wanted nor expected by the users (especially regaring the names of the lifecycle hooks). If nothing is planned for tabs & lifecycle hooks, we will be forced to keep the ugly hack based on routes to know is a user enters/leaves a tab.

At least this issue should not be closed but transformed instead in a feature request.

Any update on when this is going to be fixed from the ionic team

Worst of all, if you have this kind of routing :

-- tabs
     -- home
     -- browse
-- otherPage

Navigating between home and otherPage the lifecycle events won’t be triggered on home (at least for ionViewDidEnter or ionViewWillLeave, haven’t tested the other). They are triggered correctly on otherPage component thought.

ionViewWillEnter is triggering when navigating between tabs. It doesn’t trigger when navigating back from different page to tab.

It doesn’t work with RC0.

This also happens when using goRoot dynamically(programmatically). It wil not fire ionViewWillEnter…

Same issue here. Lifecycle functions work if your page is not inside a tab (or if you change page inside the same tab) but not when switching between two different tabs.

IonViewWillEnter only triggers when navigation is within the same tab. If you navigate to a different page in tab 1 and then back IonViewWillEnter is fired but it isn’t fired on switching tabs

On Thu, Dec 27, 2018, 4:36 PM RZR666 <notifications@github.com wrote:

ionViewWillEnter still doesn’t seem to trigger in RC0.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/ionic-team/ionic/issues/15260#issuecomment-450130337, or mute the thread https://github.com/notifications/unsubscribe-auth/AqZ_uoIiauIXjt6qJXBYc_v_LTeMKDLPks5u9KmogaJpZM4WF0ly .

What exactly is the issue?

If it’s the tab issue, then please follow https://github.com/ionic-team/ionic/issues/14566#issuecomment-416243089

If you wonder about life cycles, please read here -> https://medium.com/@paulstelzer/ionic-4-and-the-lifecycle-hooks-4fe9eabb2864

I make it work.

Be sure that if you navigate to one page in the tab, that page have the same outlet. Also with that if the navigation you don’t do it properly it will go back but will not enter in the ionViewWillEnter. For html with ionic component: href=“/main/tabs/(home:sneaker/{{sneaker.$key}})” routerDirection=“forward” Following the outlet: { path: ‘sneaker/:id’, outlet: ‘home’, component: SneakerPage },

Bump, 4.0.0-beta-17 release still has this critical issue 😦

It has been a while since the first post. Can’t believe that nobody has fixed this bug.

It might be that you redirect in your routes. So I had to check for the url in the subscription:

if (event instanceof NavigationEnd) {
          if (event.url === '/' || event.url === '/tabs' || event.url === '/tabs/(home:home)') {
            this.onEnter();
        }
}

Instead of:

 if (event instanceof NavigationEnd && event.url === '/tabs/(home:home)') {
       this.onEnter();
 }

same here, fix it please.

same here

Same issue with ionViewDidEnter.

Concerning ionViewWillLeave :

  • Switching between tabs (multiple router outlets) E.g. tabs/(home:home) to tabs/(browse:browse) -> ionViewWillLeave is never triggered Switching between pages (same router outlet) E.g. tabs/(home:home) to tabs(home:contact) -> ionViewWillEnter is triggered every time.