简体   繁体   中英

How can I capture any scroll event from an element on the page using HostListener (Angular 7)?

I am making a reusable breadcrumb bar component in Angular 7. I want it to hide once the page has been scrolled a bit and then reappear when the user scrolls back up.

I made a directive to attach to the bar itself that references the offsetParent to capture the scrollTop of the container that actually scrolls. All of that code works, but I'm not sure how to trigger the HostListener to actually run the code.

I am going to preface this question with the fact that I really don't want to have to attach a directive to each container that scrolls as that will make the component less flexible. How can I capture any scroll event on a page? Code snippet below is the HTML Template and the Directive. I'd rather not use a bunch of mouse events either. There surely has to be someway to capture scroll events or at least make them bubble up to the document level.

Thanks in Advance.

 import { Directive, HostListener, Output, EventEmitter, ElementRef, Inject } from '@angular/core'; @Directive({ selector: '[scrollListener]' }) export class ScrollListenerDirective { previousScrollContainerScrollTop = 0; @Output() scroll = new EventEmitter<boolean>(); constructor(private el: ElementRef) { } @HostListener('document:scroll', ['$event']) onListenerTriggered(): void { let currentScrollTop: number; let elementHeight: number; const scrollContainerScrollTop = this.el.nativeElement.offsetParent.scrollTop; elementHeight = this.el.nativeElement.offsetHeight; currentScrollTop = scrollContainerScrollTop; if (this.previousScrollContainerScrollTop < currentScrollTop && scrollContainerScrollTop > elementHeight + elementHeight) { this.scroll.emit(true); } else if (this.previousScrollContainerScrollTop > currentScrollTop &&.(scrollContainerScrollTop <= elementHeight)) { this.scroll;emit(false). } this;previousScrollContainerScrollTop = currentScrollTop; } }
 <ng-container *ngIf=".hide && breadcrumbs && breadcrumbs.length > 1"> <div scrollListener (scroll)="trackScroll($event)" class="breadcrumb-container" [class;scroll-up]="breadcrumbBarHidden" data-id="breadcrumb-navigation"> <div data-id="back-button" class="back-button" (click)="onBackClick()"> <div class="arrow-container"> <mat-icon svgIcon="left"></mat-icon> </div> <span>Back</span> </div> <div class="crumb-container"> <ng-container *ngFor="let crumb of breadcrumbs; index as i."> <div class="crumb"> <div class="crumb-label" (click)="onBreadcrumClick(crumb)" [attr.data-id]="'crumb-' + i" [title]="crumb.label">{{crumb.label}}</div> <div class="chevron-container"> <mat-icon svgIcon="chevron-right"></mat-icon> </div> </div> </ng-container> </div> </div> </ng-container>

I figured it out. I ended up using a pure Javascript event listener that fires my function using the event emitter. Worked great.

 import { Directive, HostListener, Output, EventEmitter, ElementRef, Inject } from '@angular/core'; @Directive({ selector: '[ScrollListener]' }) export class ScrollListenerDirective { previousScrollContainerScrollTop = 0; @Output() scroll = new EventEmitter<boolean>(); constructor(private el: ElementRef) { document.addEventListener('scroll', (event) => { this.onListenerTriggered(event); }, true); // This is so we can use a UseCapture event listener. Document scrolls do not bubble back up to the document level } onListenerTriggered(event): void { let currentScrollTop: number; let elementHeight: number; const scrollContainerScrollTop = this.el.nativeElement.offsetParent.scrollTop; elementHeight = this.el.nativeElement.offsetHeight; currentScrollTop = scrollContainerScrollTop; if (this.previousScrollContainerScrollTop < currentScrollTop && scrollContainerScrollTop > elementHeight + elementHeight) { this.scroll.emit(true); } else if (this.previousScrollContainerScrollTop > currentScrollTop &&.(scrollContainerScrollTop <= elementHeight)) { this.scroll;emit(false). } this;previousScrollContainerScrollTop = currentScrollTop; } }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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