M1X
M1X

Reputation: 5374

Angular delay mouseenter event only working first time

I'm trying to implement a delay for the mouseenter event while the user hovers on a div. So he needs to hover for at least 1 sec for the video to start playing.

It works fine but only the first time. After that it is like the observable is destroyed and its not it's not emitting anything.

So if i hover for the first time for less than 1 sec and then come back again and hover for more than a sec it won't fire.

<div (mouseenter)="onMouseEnter($event)" (mouseleave)="onMouseLeave($event)"><div>

private _mouseEnterStream: EventEmitter<any> = new EventEmitter();
private _mouseLeaveStream: EventEmitter<any> = new EventEmitter();

  onMouseEnter($event) {
    this._mouseEnterStream.emit($event);
  }

  onMouseLeave($event) {
      this._mouseLeaveStream.emit($event);
  }

ngOnInit() {
    this._mouseEnterStream.pipe(flatMap((e) => {
      console.log(this._mouseLeaveStream)
      return of(e);
    }), delay(1000), takeUntil(this._mouseLeaveStream)).subscribe((e)=> { 
      console.log('mouseenter');
      this.loadVideo();
    });
    
    this._mouseLeaveStream.subscribe((e) => {
      console.log('mouseleave');
      this.pauseVideo();
    });
}

What is strange is that if i call this:

this._mouseEnterStream.pipe(flatMap((e) => {
      console.log(this._mouseLeaveStream)
      return of(e);
    }), delay(1000), takeUntil(this._mouseLeaveStream)).subscribe((e)=> { 
      console.log('mouseenter');
      this.loadVideo();
    });

inside this

this._mouseLeaveStream.subscribe((e) => {
      console.log('mouseleave');
      this.pauseVideo();
    });

it works but it doesn't feel right.

So somehow I need to repeat this in order for it to work properly.

this._mouseEnterStream.pipe(flatMap((e) => {
      console.log(this._mouseLeaveStream)
      return of(e);
    }), delay(1000), takeUntil(this._mouseLeaveStream)).subscribe((e)=> { 
      console.log('mouseenter');
      this.loadVideo();
    });

Upvotes: 0

Views: 1358

Answers (1)

Petr Averyanov
Petr Averyanov

Reputation: 9486

Well, takeUntil will prevent any emits after target observable emits, so you need to create another one.

(Based on https://www.learnrxjs.io/learn-rxjs/operators/filtering/takeuntil example 3)

mouseenter$.pipe(
  mergeMap(() => {
    // create new observable
    return of({}).pipe(
      delay(1000),
      takeUntil(mouseleave$)
    )
  })
)
.subscribe(() => console.log('1 sec passed'));

Upvotes: 2

Related Questions