[Fixed] valueChanges does not emit value on input typing after apply switchMap

Issue

I am wondering what is wrong with my code here https://stackblitz.com/edit/angular-ivy-rc4fq8. I use widgetNameForm$ to pass to child component. Whereas switchMap should switch to valueChanges stream and emit value on input typing but such approach surprisingly does not work. Previously I used other code described bellow but it has nested subscription and I would like to stick with more reactive approach like described on stackblitz

 this.widgetName$.subscribe(val => {
  this.widgetNameForm = this.formBuilder.group({
    name: [val, {validators: Validators.required}]
  });

  this.widgetNameForm.valueChanges.pipe(
    takeUntil(this.destroy$)
  ).subscribe(val => console.log('it emits value on typing', val));
})

Solution

You have 2 different subscriptions:

  • one in constructor
  • one in template via async pipe

Your problem is that each subscription will receive a separate instance of a FormGroup. This means the instance you subscribe to in your controller is not what is being passed to the child component and bound to the form, therefore no valueChanges are ever emitted.

You can resolve this by sharing a single subscription by using the shareReplay operator:

this.widgetNameForm$ = this.widgetName$.pipe(
  map(val => this.formBuilder.group({ name: [val, {validators: Validators.required}] })),
  shareReplay() // <---
);

Check out this StackBlitz. Notice the "instance id" is shown in the input field. If you comment out the shareReplay() line you can see that you end up with 2 instances; with it you get only one.

Leave a Reply

(*) Required, Your email will not be published