Ryan Soderberg
Ryan Soderberg

Reputation: 772

Get @HostListener to wait before starting

I'm using @HostListener scroll event for angular, and I'm hoping to find a way that I can get it to wait 3 seconds before it does anything, but only the first time it is triggered

@HostListener('window:scroll', ['$event']) getScrollHeight(event) {

  const numberWhenItEntersViewport =
    document.getElementById("innerScreenSection").offsetTop -
    document.documentElement.clientHeight;
  const yValueBottomOfElement =
    document.getElementById("innerScreenSection").offsetTop +
    document.getElementById("innerScreenSection").offsetHeight;
  const elementHeight = document.getElementById("innerScreenSection")
    .offsetHeight;

  // if the element is where I want it and the timer has not gone yet then start the timer
  // I realize I never declare waitedThreeSeconds, this is just for show of what I'm thinking
  if (
    waitedThreeSeconds === false &&
    window.pageYOffset >= numberWhenItEntersViewport + 0.25 * elementHeight &&
    window.pageYOffset <= yValueBottomOfElement - 0.3 * elementHeight
  ) {
    // start timer and set waitedThreeSeconds to true? Idk how to do this without declaring
    // a varible in here and having it turned back to false everytime this function is called
    // it also does not seem to be able to read variables outside of this function
    // specifically when they change it doesnt update
  } else {
    // 3 seconds have passed
    console.log("scrolling and 3 seconds have passed");
  }
}

Upvotes: 1

Views: 2056

Answers (2)

Brad Axe
Brad Axe

Reputation: 815

    import { Subject, Observable } from 'rxjs';
    import { delay, concatMap } from 'rxjs/operators';

    // Delay amount (ms)
    const DELAY = 3000;

...

    // Setup
    private readonly eventStream = new Subject<Event>();

    // On the first emission, delay.
    // After the delay, REMAP to the original stream (concatMap)
    // USE first() to complete outer observable.
    get eventStream$(): Observable<Event> {
      return this.eventStream.pipe(
        delay(DELAY),
        first(),
        concatMap(() => this.eventStream)
      );
    }

      // Listen to clicks and emit
      @HostListener('window:scroll', ['$event']) scroll(event: Event) {
        this.eventStream.next(event);
      }

      constructor() {
        this.eventStream$.subscribe(this.isScroll);
      }

      isScroll(event: Event) {
        // Do math here.
        console.log(event);
      }

      ngOnDestroy() {
        // Cleanup.
        this.eventStream.unsubscribe();
      }

Now we could proceed to throttle responses etc.

Upvotes: 4

Raj singh
Raj singh

Reputation: 391

You may try something like below snippet. Hope it may help you.

 timeOutId:number;
    @HostListener('window:scroll', ['$event']) getScrollHeight(event) { 
    clearTimeout(this.timeOutId);
    this.timeoutId = setTimeout(() => { 
       // call your method 
    }, 3000); 
 }

Upvotes: 2

Related Questions