简体   繁体   English

Rxjs,fromEvent 处理多个事件

[英]Rxjs, fromEvent handle multiple events

I am trying to combine multiple events blur and keyup (enter key only) using fromEvent .我正在尝试使用fromEvent组合多个事件blurkeyup (enter key only) I have implemented blur event, how I can combine keyup.enter as well.我已经实现了 blur 事件,我也可以结合 keyup.enter 。

I have tried with the filter operator but with the filter, enter is working onblur is not -我已经尝试过使用filter运算符,但是使用过滤器,输入正在工作 onblur 不是 -

Component.ts组件.ts

this.propertyDescription.forEach((input: ElementRef) => {
    const events = ['blur', 'keyup'];
    from(events)
    .pipe(
        takeUntil(this.unsubscribe$),
        mergeMap((event) =>
            fromEvent(input.nativeElement, event)
        ),
        filter((e: KeyboardEvent) => e.key === 'Enter'),
        map((evt: any) => evt.target.value),
        distinctUntilChanged(
            (pre: any, curr: any) =>
                JSON.stringify(pre) === JSON.stringify(curr)
            )
        )
        .subscribe((caption: string) => {
            console.log(caption);
        });
});
  1. Subscription inside a forEach is an inelegant design. forEach中的订阅是一种不雅的设计。 It'd lead to multiple (potentially unhandled) subscriptions.它会导致多个(可能未处理的)订阅。 You could use merge with Array#map .您可以将mergeArray#map

  2. Also instead of using from you could use merge with multiple fromEvent s.另外from您可以使用与多个fromEvent merge ,而不是使用from

Try the following尝试以下

const events = ['blur', 'keyup'];

merge(
  this.propertyDescription.map((input: ElementRef) =>
    merge(
      events.map((event: string) => 
        fromEvent(input.nativeElement, event).pipe(
          map((evt: any) => evt.target.value),
          distinctUntilChanged((pre: any, curr: any) =>
            JSON.stringify(pre) === JSON.stringify(curr)
          )
        )
      )
    )
  )
).pipe(
  takeUntil(this.unsubscribe$)
).subscribe((caption: string) => {
  console.log(caption);
});

What you are doing now is sending "blur" and "keyup" to your main observable.您现在正在做的是将“blur”和“keyup”发送到您的主要可观察对象。

What you need to do is declare what the "keyup" event does, what the "blur" event does and the apply your logic.您需要做的是声明“keyup”事件的作用,“blur”事件的作用以及应用您的逻辑。

Something more like:更像是:

this.propertyDescription.forEach((input: ElementRef) => {
  const blurEvent$ = fromEvent(input.nativeElement, 'blur').pipe(/* your logic for "blur" event */);
  const keyupEvent$ = fromEvent(input.nativeElement, 'keyup').pipe(/* your logic for "keyup" event */);
  merge(blurEvent$, keyupEvent$).pipe(
    takeUntil(this.unsubscribe$),
    /* rest of your logic */
  )
  .subscribe();
}

Edit: merge does not take an array.编辑:合并不接受数组。 see on stackblitzstackblitz看到

better way to do it in angular would be to send events from template更好的方法是从模板发送事件

<input #inp (keyup.enter)="valueUpdates$.next(inp.value)" (blur)="valueUpdates$.next(inp.value)">


//ts
valueUpdates$ = new Subject<string>();


this.valueUpdates$
  .pipe(distinctUntilChanged())
  .subscribe((caption: string) => console.log(caption));

If you just want to listen to changes that have been made after leaving the input element ( blur ) or after the user clicked Enter, you could just use the change event instead.如果您只想听听离开输入元素 ( blur ) 或用户单击 Enter 后所做的更改,则可以改用change事件。

However, if there is some reason you explicitly want to use blur and keyup with Enter, you have to fix your filter operator.但是,如果您keyup某种原因明确希望在 Enter 中使用blurkeyup ,则必须修复filter运算符。 Right now, you're filtering out all Events that have no key property with the value 'Enter'.现在,您正在过滤掉所有没有值为“Enter”的key属性的事件。 The FocusEvent blur doesn't have that property, so the filter function returns false . FocusEvent blur没有该属性,因此 filter 函数返回false

A working filter should look something like this:工作过滤器应如下所示:

filter((e: KeyboardEvent | FocusEvent) => e instanceof FocusEvent || e.key === 'Enter'),

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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