Eugene Khristo
Eugene Khristo

Reputation: 79

How to combine two streams in RxJs and a bit more?

I have a reactive form. As I'm typing and stop for 3 secs - it should console.log(form.value). But when I click submitconsole.log(form.value) should be logged immediately and also prevent making previous console.log() that was waiting for 3 secs. And after as I'm typing - and not press submit - it should console.log() after 3 secs again.

I'm pretty newbie to to RxJs. I've just figured out how to make the first part using debounceTime() operator. But I cannot wrap my head around how to "inject" submit event into stream of the form and prevent it from console.log();

Link on stackblitz

component.html

<form [formGroup]="form" (ngSubmit)="onSubmit()">
  <input type="text" formControlName="name" placeholder="name"><br>
  <input type="text" formControlName="age" placeholder="age"><br>

  <button>Save</button>
</form>

component.ts

export class AppComponent implements OnInit  {
  form: FormGroup;

  constructor(private fb: FormBuilder) {}

  ngOnInit() {
    this.form = this.fb.group({
      'name': [],
      'age': []
    });

    this.form.valueChanges.pipe(
      debounceTime(3000)
    ).subscribe(value => console.log(value));
  }

  onSubmit() {
    console.log(this.form.value);
  }
}

Expected behavior:

when I'm typing, stop for 2 secs - nothing happens, if I stop then for 3 secs or more then console.log(form.value);

When press submit should console.log(form.value) right away and cancel previous waiting of first case.

Upvotes: 1

Views: 634

Answers (2)

Davy
Davy

Reputation: 6441

Solution: https://stackblitz.com/edit/angular-gn1dwx

So, thinking in streams, we have:

  • a stream of submits
  • a stream of debounced change events

We want to avoid duplicate events. So, we merge our 2 streams, and add the distinctUntilChanged operator to avoid duplicate values. We serialize/deserialize since we dont want distinct to operate on instances, but values.

To cleanup our subscription when this component is destroyed, we use takeUntil to automatically close the observable, which automatically will take care of our subscription (always clean up subscriptions!)

Note: changing a value, waiting 4 seconds and then clicking submit will not trigger the subscription. I assume this is intended behavior.

Upvotes: 1

Bunyamin Coskuner
Bunyamin Coskuner

Reputation: 8859

You can simply unsubscribe from the Observable when the form is submitted.

Check it out

export class AppComponent implements OnInit  {
  form: FormGroup;

  subscription;

  constructor(private fb: FormBuilder) {}

  ngOnInit() {
    this.form = this.fb.group({
      'name': [],
      'age': []
    });

    this.subscription = this.form.valueChanges.pipe(
      debounceTime(3000)
    ).subscribe(value => console.log(value));
  }

  onSubmit() {
    this.subscription.unsubscribe();
    console.log(this.form.value);
  }
}

Upvotes: 0

Related Questions