Search code examples
ionic-frameworkionic4

How to hide header on scroll in ionic 4?


I wanted to know how I can hide a header in Ionic 4 by scrolling down the page, and re-show it when scrolling up.

I found many solutions on how to do that, but they all turned out to not working or being out-of-date.

So I collected all piece of information I could find to provide this answer.


Solution

  • Thanks to this video I got it to work.

    First of all call ionic g directive directives/hide-header. You can of course replace directive/hide-header with your own path and name.

    hide-header.directive.ts

    import { Directive, HostListener, Input, OnInit, Renderer2 } from '@angular/core';
    import { DomController } from '@ionic/angular';
    
    @Directive({
        selector: '[appHideHeader]'
    })
    export class HideHeaderDirective implements OnInit {
    
        @Input('header') header: any;
    
        private lastY = 0;
    
        constructor(
            private renderer: Renderer2,
            private domCtrl: DomController
        ) { }
    
        ngOnInit(): void {
            this.header = this.header.el;
            this.domCtrl.write(() => {
                this.renderer.setStyle(this.header, 'transition', 'margin-top 700ms');
            });
        }
    
        @HostListener('ionScroll', ['$event']) onContentScroll($event: any) {
            if ($event.detail.scrollTop > this.lastY) {
                this.domCtrl.write(() => {
                    this.renderer.setStyle(this.header, 'margin-top', `-${ this.header.clientHeight }px`);
                });
            } else {
                this.domCtrl.write(() => {
                    this.renderer.setStyle(this.header, 'margin-top', '0');
                });
            }
    
            this.lastY = $event.detail.scrollTop;
        }
    
    }
    

    After that, in your template:

    <ion-header #header>
        <ion-toolbar><ion-title>Test</ion-title></ion-toolbar>
    </ion-header>
    <ion-content scrollEvents="true" appHideHeader [header]="header">
    </ion-content>
    

    Take care of the scrollEvents, appHideHeader and the [header] attributes! The last one takes the header element as argument, in this case #header.


    Most of the code is the same as shown in the video. I changed the host-property from the @Directive and used the more up-to-date HostListener.

    If you want to use the directive in more than one directive, you need to create a SharedModule.

    To do so, create the module with ng g module shared. After that, add the HideHeaderDirective to the declarations and the exports array.

    shared.module.ts

    import { NgModule } from '@angular/core';
    import { CommonModule } from '@angular/common';
    import { HideHeaderDirective } from './directives/hide-header.directive';
    
    
    @NgModule({
        declarations: [HideHeaderDirective],
        exports: [HideHeaderDirective],
        imports: [
            CommonModule
        ]
    })
    export class SharedModule {}
    
    

    Now add the shared module to all the modules you want to use the directive in.

    Note: You cannot import the directive in app.module.ts and use it in a submodule! You have to import the shared module in every direct module you want to use the directive in.

    My current versions of node, npm and ionic:

    versions