Angular-Material Sidenav cdkScrollable

Springrbua picture Springrbua · Nov 28, 2017 · Viewed 17.3k times · Source

The Angular Material CDK provides a Directive CdkScrollable, which allows you to listen to ScrollEvents of a specific container.
I am now trying to access the CdkScrollable of the MatSidenavContent, which is added by default.
However my @ViewChild(CdkScrollable) and @ContentChild(CdkScrollable) are always undefined.

My Component looks something like this:

<mat-sidenav-container>
    <mat-sidenav>Sidenav content</mat-sidenav>
    <div>Main content</div>
</mat-sidenav-container>

The resulting DOM looks something like this:

<mat-sidenav-container>
    <div class="mat-drawer-backdrop"></div>
    <div tabindex="-1" class="cdk-visually-hidden cdk-focus-trap-anchor"></div>
    <mat-sidenav>Sidenav content</mat-sidenav>
    <mat-sidenav-content cdkScrollable>
          <div>Main content</div>
    </mat-sidenav-content>
</mat-sidenav-container>

The mat-sidenav-content Component, which is generated automatically, uses a CdkScrollable-Directive, which I need to access.
My question is now:
Is it possible to access that Directive and if so, how?

Answer

Sebastian Denis picture Sebastian Denis · Jun 12, 2018
  1. Add to your app module imports: ScrollDispatchModule.
  2. Add cdkScrollable to your mat-sidenav-content:

<mat-sidenav-content cdkScrollable> </mat-sidenav-content>

  1. In your root component:

a) inject ScrollDispatcher from @angular/cdk/overlay and subscribe to scrolling:

constructor(public scroll: ScrollDispatcher) {

    this.scrollingSubscription = this.scroll
          .scrolled()
          .subscribe((data: CdkScrollable) => {
            this.onWindowScroll(data);
          });
}

c) do something when scrolling, e.g. check the offset

private onWindowScroll(data: CdkScrollable) {
    const scrollTop = data.getElementRef().nativeElement.scrollTop || 0;
    if (this.lastOffset > scrollTop) {
      // console.log('Show toolbar');
    } else if (scrollTop < 10) {
      // console.log('Show toolbar');
    } else if (scrollTop > 100) {
      // console.log('Hide toolbar');
    }

    this.lastOffset = scrollTop;
  }

Documentation: https://material.angular.io/cdk/scrolling/api

Update Angular 9 :

Use import {ScrollingModule} from '@angular/cdk/scrolling', ScrollDispatchModule is deprecated