简体   繁体   English

如何检测 mat-sidenav-container 中的滚动事件

[英]How to detect scroll events in mat-sidenav-container

I can't figure out how to detect when the mat-sidenav-container scrolls in angular material 2.我不知道如何检测 mat-sidenav-container 何时在角材料 2 中滚动。

I would like to call a method on my component when a user scrolls.当用户滚动时,我想在我的组件上调用一个方法。 However when using the sidenav-container the scroll event is no longer fired on the window.但是,当使用 sidenav-container 时,不再在窗口上触发滚动事件。

Instead an extra <mat-sidenav-content cdkscrollable></mat-sidenav-content> element is added and this is where the scroll bars are.而是添加了一个额外的<mat-sidenav-content cdkscrollable></mat-sidenav-content>元素,这就是滚动条所在的位置。 How can I detect when scrolling occurs on this component if I can't directly access it to put an (scroll)="myMethod()" event listener on it.如果我无法直接访问它以在其上放置(scroll)="myMethod()"事件侦听器,我如何检测该组件上何时发生(scroll)="myMethod()"

Any ideas?有什么想法吗?

Instead of calling a method on every scroll event you could create an Observable of scroll events and subscribe to it.您可以创建一个滚动事件的 Observable 并订阅它,而不是在每个滚动事件上调用一个方法。

Using Observable使用 Observable

enum Direction {
    Up = 'Up',
    Down = 'Down'
}

ngAfterViewInit() {
    const content = document.querySelector('.mat-sidenav-content');
    const scroll$ = fromEvent(content, 'scroll').pipe(
      throttleTime(10), // only emit every 10 ms
      map(() => content.scrollTop), // get vertical scroll position
      pairwise(), // look at this and the last emitted element
      map(([y1, y2]): Direction => (y2 < y1 ? Direction.Up : Direction.Down)), // compare this and the last element to figure out scrolling direction
      distinctUntilChanged(), // only emit when scrolling direction changed
      share(), // share a single subscription to the underlying sequence in case of multiple subscribers
    );

    const goingUp$ = scroll$.pipe(
      filter(direction => direction === Direction.Up)
    );

    const goingDown$ = scroll$.pipe(
      filter(direction => direction === Direction.Down)
    );

    goingUp$.subscribe(() => console.log('scrolling up');
    goingDown$.subscribe(() => console.log('scrolling down');
}

For further explanation of the code above check out: https://netbasal.com/reactive-sticky-header-in-angular-12dbffb3f1d3有关上述代码的进一步解释,请查看: https : //netbasal.com/reactive-sticky-header-in-angular-12dbffb3f1d3

My current Version Angular 8我当前的版本 Angular 8
Solution 1:解决方案1:

  • Check if you content is placed inside the检查您的内容是否放置在

     <mat-sidenav-container fullscreen> </mat-sidenav-container>
  • With fullscreen property above any of the window methods like window.scroll() and the properties like window.pageYOffset will not work在任何窗口方法(如 window.scroll() 和window.pageYOffset等属性)上方使用全屏属性将不起作用

  • Remove fullscreen and try.删除全屏并尝试。 It will work strong text它将工作强大的文本

Solution 2: You want to keep the property fullscreen解决方案 2:您想保持属性全屏

  • Check if you content is placed inside the检查您的内容是否放置在

     <mat-sidenav-container fullscreen> <mat-sidenav></mat-sidenav> <div> //your content </div> </mat-sidenav-container>
  • In above i did't put my content inside a mat-sidenav-content like below, since angular places it for you by default inside a mat-sidenav-content tag gives us the benefit of default behaviour在上面,我没有将我的内容放在像下面这样的 mat-sidenav-content 中,因为 angular 默认情况下将它放在 mat-sidenav-content 标签中,这为我们提供了默认行为的好处

     <mat-sidenav-content> <div> //your content </div> </mat-sidenav-content>
  • import {MatSidenavModule} from '@angular/material/sidenav';从“@angular/material/sidenav”导入 {MatSidenavModule}; in app.module.ts and declare in imports array.在 app.module.ts 中并在导入数组中声明。

  • In your component in which you would like to get scroll event to do some stuff when the scroll position changes.在您希望滚动事件在滚动位置更改时执行某些操作的组件中。 Do the following执行以下操作

    import { Component, NgZone , OnInit } from '@angular/core';
    import { ScrollDispatcher } from '@angular/cdk/scrolling';
    import { CdkScrollable } from '@angular/cdk/scrolling';
    @Component({
      selector: 'app-scroll-top',
      templateUrl: './scroll-top.component.html',
      styleUrls: ['./scroll-top.component.css']
    })
    export class ExampleComponent implements OnInit {


      constructor (private scrollDispatcher: ScrollDispatcher, private zone: NgZone) {}

      ngOnInit() {
      }

      ngAfterViewInit() {
        this.scrollDispatcher.scrolled().
        subscribe((cdk: CdkScrollable)  => {
        this.zone.run(() => {
        //Here you can add what to happen when scroll changed
        //I want to display the scroll position for example
          const scrollPosition = cdk.getElementRef().nativeElement.scrollTop;
          console.log(scrollPosition);
        });
        });
      }

Could you show me your css file?你能告诉我你的css文件吗? I also experienced the same problem, but due to the following css being applied to mat-sidenav-container.我也遇到了同样的问题,但由于以下 css 被应用于 mat-sidenav-container。

height: 100vh;

Rather than letting Angular automatically insert the tag, include the side-nav-content tag in your HTML.与其让 Angular 自动插入标签,不如在 HTML 中包含side-nav-content标签。 Then you can add the listener to it.然后,您可以向其中添加侦听器。

<mat-sidenav-container>
  <mat-sidenav>
  </mat-sidenav>
  <mat-sidenav-content (scroll)="myScrollHandler($event)">
  </mat-sidenav-content>
</mat-sidenav-container>

As soon as <mat-sidenav-content> has the cdkScrollable Directive, you can get it in your component thanks to @ViewChild decorator:一旦<mat-sidenav-content>拥有 cdkScrollable 指令,您就可以通过 @ViewChild 装饰器将其添加到您的组件中:

@ViewChild(CdkScrollable) scrollable: CdkScrollable;

Then you can observe the scroll behaviour by subscribing to the elementScrolled Observable:然后你可以通过订阅 elementScrolled Observable 来观察滚动行为:

this.scrollable.elementScrolled().subscribe(scrolled => console.log('scrolled', scrolled));

You should use Material2 example "Sidenav with a FAB" .您应该使用 Material2 示例"Sidenav with a FAB"

Please wrap scrollable content with div:请用 div 包裹可滚动内容:

<mat-sidenav-container class="example-sidenav-fab-container">
  <mat-sidenav #sidenav mode="side" opened="true">
   ...
  </mat-sidenav>
  <div class="example-scrolling-content" (scroll)="handleScroll($event)">
    ... content ...
  </div>
</mat-sidenav-container>

and this should be your css:这应该是你的css:

.example-scrolling-content {
  overflow: auto;
  height: 100%;
}

Try adding fixedInViewport="true"尝试添加fixedInViewport="true"

For more styling: [style.marginTop.px]="56"更多样式: [style.marginTop.px]="56"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM