Angular-Material Sidenav cdkScrollable

Angular-Material Sidenav cdkScrollable

Angular MaterialCDK 提供了DirectiveCdkScrollable,可以监听特定容器的ScrollEvent
我现在正在尝试访问默认添加的 MatSidenavContentCdkScrollable
但是我的 @ViewChild(CdkScrollable)@ContentChild(CdkScrollable) 总是未定义的。

我的 Component 看起来像这样:

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

结果 DOM 看起来像这样:

<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>

自动生成的mat-sidenav-contentComponent使用了CdkScrollable指令,我需要访问它。
我现在的问题是:
是否可以访问 Directive,如果可以,如何访问?

前段时间我在@angular/material 上开了一个 Issue,他们现在公开了 CdkScrollable-Instance。
要使用它,您需要使用 @ViewChild(MatSidenavContainer 访问 MatSidenavContainer。此实例有一个 public 成员 scrollable,即 CdkScrollable 实例。
可以找到一个示例 here

编辑: 由于示例不是很完整,有些人在实现它时遇到困难,我将在这里编写自己的示例:

HTML:

<mat-sidenav-container>
    <mat-sidenav #sidenav>
        Sidenav Content
    </mat-sidenav>
    <div>
        Main Content
    </div>
</mat-sidenav-container>

TypeScript:

import { Component, AfterViewInit, ViewChild } from '@angular/core';
import { MatSidenavContainer } from '@angular/material';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent implements AfterViewInit  {
  @ViewChild(MatSidenavContainer) sidenavContainer: MatSidenavContainer;

    constructor() {
    }

    ngAfterViewInit() {
      console.log(this.sidenavContainer.scrollable);
    }
}

重要:

  1. 不要使用 <mat-sidenav-content>。此标记是自动生成的,并且附加了 cdkScrollable 指令。如果您在自己的模板中使用 <mat-sidenav-content>,则 scrollable 将是未定义的。
  2. 使用 AfterViewInit 而不是 OnInit。据我所知,@ViewChild 已在 AfterViewInit 中解决,OnInit 可能为时过早。
  1. 添加到您的应用模块导入:ScrollDispatchModule
  2. cdkScrollable 添加到您的 mat-sidenav-content:

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

  1. 在你的根组件中:

a) 从 @angular/cdk/overlay 注入 ScrollDispatcher 并订阅滚动:

constructor(public scroll: ScrollDispatcher) {

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

c) 滚动时做一些事情,例如检查偏移量

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;
  }

文档:https://material.angular.io/cdk/scrolling/api

更新 Angular 9 :

使用 import {ScrollingModule} from '@angular/cdk/scrolling'ScrollDispatchModule 已弃用