Home > Enterprise >  Custom distinctUntilChanged implementation
Custom distinctUntilChanged implementation

Time:12-22

In our Angular application we use distinctUntilChanged() quite often and we are at a point where we want to use it to compare form.valueChanges directly. As described in this question: https://stackoverflow.com/a/53825991/1003686 using distinctUntilChanged on the form.valueChanges is not going to work properly:

this.myFormControl.valueChanges
  .pipe(distinctUntilChanged())
  .subscribe(newValue => {
    console.log('fires endlessly');
  });

and instead I have to write it like this to get a very basic comparison working.

this.searchAndFilterForm.valueChanges
  .pipe(distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b))
  .subscribe(newValue => {
    console.log('fires only on real changes');
  });

I don't want to define a custom compare on each form valuechange and instead I want to have a new Pipe operator called formDistinctUntilChanged() that I can use and refactor if needed.

I saw that distinctUntilChanged() is a MonoTypeOperatorFunction. How can I implement a custom MonoTypeOperatorFunction so that I get a formDistinctUntilChanged() operator? Preferably just using the normal distinctUntilChanged() with a predefined compare.

Basically I am looking for something that is doing the same as the normal distinctUntil but with a predefined compare that I can reuse in multiple components.

this.myFormControl.valueChanges
  .pipe(formDistinctUntilChanged())
  .subscribe(newValue => {
    console.log('fires only on real changes');
  });

Creating a custom rxjs operator like it is described in https://tane.dev/2021/01/creating-custom-rxjs-operators/ does not really work in my angular environment because we have eslint(prefer-arrow/prefer-arrow-functions) defined and I do not fully understand how to use another MonoTypeOperatorFunction in a MonoTypeOperatorFunction.

CodePudding user response:

A pipeable operator is just a function that accepts a observable and returns an observable. So you could use something like this:

const formDistinctUntilChanged =
  <T>() =>
  (obs$: Observable<T>): Observable<T> =>
    obs$.pipe(distinctUntilChanged(/*your comparator*/));
  • Related