Home > database >  Create Observable from multiple FormControl
Create Observable from multiple FormControl

Time:03-25

I have an Observable<FormGroup> that has a couple of boolean FormControl

readonly someForm$ = model$.pipe(map((model: Model) => {
  return new FormGroup({
    foo: new FormControl(model.getFoo()),
    bar: new FormControl(model.getBar()),
  });
}));

I would like to create an observable that emits if any of the FormControl values are true. I tried the following

readonly result$ = someForm$.pipe(switchMap(
  form => form.valueChanges.pipe(
    map(changes => changes.foo || changes.bar),
    startWith(() => form.value['foo'] || form.value['bar'])
  )
));

Though result$ always resolves to true during testing. What is the proper way to create an observable that is essentially foo || bar?

Minimal example: https://stackblitz.com/edit/angular-material-bvy7bj

CodePudding user response:

There're several issues:

  • You have result$ in your component and $result in your template.

  • startWith() doesn't accept a function, it needs to be a value in your use-case.

  • You make two subscriptions to someForm$ which creates two unrelated FormGroup instances. You'll need to use shareReplay(1) at the end of someForm$.

Your updated demo: https://stackblitz.com/edit/angular-material-xpqmcs?file=app/app.component.ts

CodePudding user response:

use filter operator to filter out falsey values

const result$ = someForm$.pipe(
  switchMap((form) =>
    form.valueChanges.pipe(
      filter((changes) => changes.foo || changes.bar),
      map((changes) => changes.foo || changes.bar)
    )
  )
);

I have created simulated form and simulated user events

import { BehaviorSubject, of } from 'rxjs';
import { filter, map, startWith, switchMap } from 'rxjs/operators';
const someForm$ = of({ // custom Observable form
  valueChanges: new BehaviorSubject({
    foo: false,
    bar: false,
  }),
  value: {
    foo: false,
    bar: false,
  },
});

const result$ = someForm$.pipe(
  switchMap((form) =>
    form.valueChanges.pipe(
      filter((changes) => changes.foo || changes.bar), // filtering falsey values
      map((changes) => changes.foo || changes.bar) // map to true
    )
  )
);

result$.subscribe((data) => {
  console.log(data); 
});

someForm$.subscribe((data) => {
  data.valueChanges.next({ foo: false, bar: true }); // custom user event
  data.valueChanges.next({ foo: false, bar: false }); // custom user event
  data.valueChanges.next({ foo: true, bar: false }); // custom user event
});

demo:

https://stackblitz.com/edit/typescript-tfqjms?file=index.ts&devtoolsheight=100

  • Related