I have a fromEvent attached to input keydown event. This way I can listen to KeyEvents.
Inside the pipe, I use the scan operator, so I can accumulate the latest 3 keys introduced by the user.
I check in the scan, the accumulator length, so if it's already three, I clean it up (manual reset).
I need a way that when the user types in, within the next 3000ms, he can keep typing until reaching the limit (3 keys) but if the user is slower than the time limit (3s), next time he types in, I will reset the accumulator manually.
fromEvent(myInput.nativeElement, 'keydown').pipe(
tap(e => e.preventDefault()),
scan((acc: KeyboardEvent[], val: KeyboardEvent) => {
// Add condition here to manually reset the accumulator...
if (acc.length === 3) {
acc = [];
}
return [...acc, val];
}, []),
takeUntil(this.destroy$)
).subscribe((events: KeyboardEvent[]) => console.log(events));
I have tried to merge this with a timer in some way, but I can't figure out how. Not sure how to get there.
You can use the timeInterval
operator here, which gives you the time passed between emissions along with the value. set up along the lines of:
fromEvent(myInput.nativeElement, 'keydown').pipe(
tap(e => e.preventDefault()),
timeInterval(), // just add this operator, will convert to shape {value: T, interval: number}
scan((acc: KeyboardEvent[], val) => {
// Add condition here to manually reset the accumulator...
// also check the interval
if (acc.length === 3 || val.interval > 3000) {
acc = [];
}
return [...acc, val.value];
}, []),
takeUntil(this.destroy$)
).subscribe((events: KeyboardEvent[]) => console.log(events));
Here is a working blitz: https://stackblitz.com/edit/rxjs-dxfb37?file=index.ts
Not an operator I've ever had a use case for before, but seems to solve your issue here pretty effectively.