[英]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 并订阅它,而不是在每个滚动事件上调用一个方法。
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
等属性)上方使用全屏属性将不起作用
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.