Abhijit Srivastava
Abhijit Srivastava

Reputation: 1459

Why RxJs Record 2 events on long keypress?

I am trying to build a UI that responses to keyPress event.

I am using Angular and RxJS to detect an event. [Packages are uptodate]

The code looks like

this.keyboard$ = Observable.fromEvent(document, 'keypress')
     .pipe(debounceTime(300))
     .subscribe(e => {console.log(e);})

This code works fine in a normal scenario, but the edge case when the user presses a key for too long this records the second press event once the key is released.

There is a work around that I found, but keyup defeats the purpose.

this.keyboard$ = Observable.fromEvent(document, 'keyup')
     .pipe(debounceTime(300))
     .subscribe(e => {console.log(e);})

I need to detect one event per keypress.

Can anyone please point out what is wrong with the snippet? Thanks in advance.

Upvotes: 1

Views: 6065

Answers (2)

William Martins
William Martins

Reputation: 442

Actually its not a bug. When you hold a key, the browser resend the same event. Its Called Key Repeat.

Reference: https://developer.mozilla.org/en-US/docs/Web/Events/keypress

To avoid the Key Repeat, you could filter repeated events using the 'repeat' property.

const { fromEvent} = rxjs;
const {filter, map} = rxjs.operators;

var keyboard$ = fromEvent(document, 'keydown')
  .pipe(filter(event => !event.repeat))
  .subscribe(event => {
    console.log(event.code);

  })

Ive created a JSFiddle here so you can try it by yourself: https://jsfiddle.net/williamxsp/Lq9go1bt/

Upvotes: 5

Michael Knight
Michael Knight

Reputation: 265

I'm not familiar with Angular but I think it would look something like this:

have a variable which holds the key code of the most recently pressed key and another variable which will determine if the event will cause your function to be called. Each time a key is pressed call you function then don't allow your function to be called again until you hear a keyup event with the right code

var KeyUpHasOccurred = true;
var KeyCode;

this.keyboard$ = Observable.fromEvent(document, 'keydown')
 .pipe(debounceTime(300))
 .subscribe(e => {
     if(KeyUpHasOccurred)
         console.log(e);
         KeyUpHasOccurred = false;
         KeyCode = e.key
 })

this.keyboard$ = Observable.fromEvent(document, 'keyup')
 .pipe(debounceTime(300))
 .subscribe(e => {
      if(e.key = KeyCode)
          KeyUpHasOccurred = true;
  })

Upvotes: 1

Related Questions