angularionic4

Component within page not animating on navigate for iOS


When navigating to a new screen by calling NavController.navigateForward('/url') you get a free native animation which slides the screen in to view. This works as expected unless I use a component within a page component. When I do that, everything animates as expected except the component within the page.

When the following page is navigated to the content and title all slide into view as expected.

<ion-header>
    <h1>The Title</h1>
</ion-header>
<ion-content>
    Some content...
</ion-content>

However, if I extract the h1 tag to a component only the "Some content..." slides into view. "The Title" is displayed with no animation.

<ion-header>
    <app-my-component>The Title</app-my-component>
</ion-header>
<ion-content>
    Some content...
</ion-content>

Solution

  • The reason why that's happening is because Ionic expects the ion-title to be in a certain place for it to be animated. You can see that by inspecting the the source code of the iOS page transition.

    As you can see here Ionic gets the entering ion-toolbar like this:

    const enteringToolBarEls = enteringEl.querySelectorAll(':scope > ion-header > ion-toolbar');
    

    And here it gets the ion-title like this:

    enteringTitle.addElement(enteringToolBarEl.querySelector('ion-title'));
    

    That won't work since the structure of the HTML code will be different if you use a custom component in your ion-header:

    ion-header > your-component > ion-toolbar
    

    It's recommended not to use a custom component in the ion-header because Ionic expects it to be in a specific way in order to animate it properly.


    That being said, if you really need to use a custom component there, you can crate your own custom page transition like this:

    1. Create a new file myAwesomeTransitionAnimation.ts with the content of the source code of the iOS page transition.
    2. Edit the code to make the transition work with your specific HTML structure
    3. Edit the app.module.ts file to use that transition instead of the default:
    imports: [
        ...
        IonicModule.forRoot({  
          navAnimation: myAwesomeTransitionAnimation,
        }), 
      ],
    

    Please keep in mind that doing so would override the default "animation" of all ion-nav and ion-router-outlet across the whole application.

    If you just want to override it for iOS (using the default for Android), please take a look at this comment:

    let ionic = [
      IonicModule.forRoot()
    ];
    
    const platform = new Platform();
    
    if (platform.is('ios')) {
      ionic = [
        IonicModule.forRoot({
          navAnimation: myAwesomeTransitionAnimation,
        })
      ]
    }
    

    And in module imports:

    imports: [ ...ionic, ]