Angular Reactive Forms: Debounce only some specific Form Control

15,919

Solution 1

Debounce the text control's valueChanges observable, then use combineLatest() to combine it with the checkbox control's valueChanges observable.

Simple example

Solution 2

Create each individual FormControl before adding them to the form group and then you can control the valueChanges observable per FormControl

this.textInput.valueChanges
      .pipe(
        debounceTime(400),
        distinctUntilChanged()
      )
      .subscribe(res=> {
        console.log(`debounced text input value ${res}`);
      });

the distinctUntilChanged will make sure only when the value is diffrent to emit something.

Solution 3

Debounce for a single control in a form group can be done by

   this.form.get('textInput')
  .valueChanges
  .pipe(debounceTime(500))
  .subscribe(dataValue => {
    console.log("dataValue", dataValue);
  });

Solution 4

Right now I had that problem, I solved it as follows!

// Reactive control
fieldOne = this.formBuilder.control('');

// Reactive form
formGroup = this.formBuilder.group({
  fieldOne: [],
  fieldTwo: [],
  fieldX: [],
});

this.fieldOne.valueChanges
  .pipe(debounceTime(300))
  .subscribe(value => {
    this.formGroup.get('fieldOne').setValue(value);
  });

you have response speed in the controls within the form group and a delay in the events emitted from the individual control, hopefully in the future that the valueChanges emitted by the formGroup will present the control that triggered the event and be able to use filter in the observable

Regards!

Share:
15,919

Related videos on Youtube

Benjamin M
Author by

Benjamin M

Updated on April 07, 2022

Comments

  • Benjamin M
    Benjamin M about 2 years

    I have a simple Search Component which contains a Reactive Form with 2 elements:

    • Text Input (to search for arbitrary matching text)
    • Checkbox (to include / exclude deleted results)

    So far I use myFormGroup.valueChanges.subscribe(...) to execute my search method.

    Now the problem is, that I want to debounce the text input. And at the same time not debounce the checkbox, so the search method is getting executed instantly when clicking the checkbox.

    Using valueChanges.debounceTime(500) will of course debounce the whole form. That's not what I want.

    This is a stripped down example. The real form has some more inputs. Some should be debounced and some shouldn't.

    Is there any easy way to get this done? Or do I have to subscribe to every form control separately?

    Would be nice to see how you did solve this.

    Thanks in advance.


    EDIT: Code

    export class SearchComponent {
    
      myFormGroup: FormGroup;
    
      constructor(fb: FormBuilder) {
        this.myFormGroup = fb.group({
          textInput: '',
          checkbox: false
        });
      }
    
      ngOnInit() {
        this.myFormGroup.valueChanges.subscribe(val => {
          // debounce only the textInput,
          // and then execute search
        });
      }
    
    }
    
    • yurzui
      yurzui about 6 years
    • Benjamin M
      Benjamin M about 6 years
      Looks quite hacky, but seems to work. Another idea: Maybe there's some way to see which value inside the FormGroup changed? Then I could do something like valueChangesDiff.debounce(diff => diff.textInput ? 500 : 0)
  • Benjamin M
    Benjamin M about 6 years
    My real form has 4 Text Inputs and lot's of Checkboxes and Selects. I don't want combineLatest with over 20 form controls. There must be another way.
  • JB Nizet
    JB Nizet about 6 years
    Then why didn't you ask that in the first place? But anyway, Doing more complex stuff requires more effort.
  • Benjamin M
    Benjamin M about 6 years
    I'll quote myself: "This is a stripped down example. The real form has some more inputs. Some should be debounced and some shouldn't."
  • JB Nizet
    JB Nizet about 6 years
    Sorry, I missed that in the question.
  • Benjamin M
    Benjamin M about 6 years
    But thank you, I'll highlight this part of the question.
  • yurzui
    yurzui about 6 years
    Create each individual FormControl before but he already has all controls and he already can control valueChanges per FormControl
  • Daniel Netzer
    Daniel Netzer about 6 years
    that's true, I just offered the way I usually do that.
  • Manduro
    Manduro about 6 years
    I created a function that does exactly this, but in an easy way for lots of form controls: stackblitz.com/edit/…
  • callmemath
    callmemath almost 5 years
    import { debounceTime, distinctUntilChanged } from "rxjs/operators"; Your welcome :)