16

I have text box and assigned to it keyup event a search function but I want it to happen with delay, not on every keypress

here is the html code :

<input type="text" [(ngModel)]="searchedKPI" (keyup)="searchConfigTree()">

and here is ts code :

list = list.filter(item => item.label.toLocaleLowerCase().includes(this.searchedKPI.toLocaleLowerCase())).slice();

and here is the example I wanted to search "text" string but the event happens 4 times, I want to this happens once only for "text" string :

enter image description here

what the solution?

4
  • what is wrong ? Commented Oct 3, 2017 at 5:40
  • i want to this happens once only for "text" string Commented Oct 3, 2017 at 5:41
  • try using debounce....! Commented Oct 3, 2017 at 5:41
  • 2
    this may help stackoverflow.com/a/36849347/5621827 Commented Oct 3, 2017 at 5:53

4 Answers 4

21

Welcome to the Observable's world. Just use Observable to get the desired result. Get the reference of your input in the component and use this code. debounceTime will let the event to trigger at least after 1 second from the previous trigger. It will let you not to fire on every keyup when user types fast.

Observable.fromEvent(yourInput, 'keyup').debounceTime(1000).subscribe(value => /* */)

In the subscribe method you can write your logic. The value is the value of the input.

Sign up to request clarification or add additional context in comments.

4 Comments

Getting error Observable.fromEvent is not a function - using rxjs 6.3.3
@amphetamachine use only fromEvent
Using rxjs higher than 6 version requires just fromEvent instead of Observable.fromEvent
thanks for your help, it help me a lot =D but complement with
14

View template.html

<input type="text" [(ngModel)]="searchedKPI" (keyup)="searchConfigTree()" #something>

component.ts (do not forget implement the AfterViewInit)

     source: any;
     @ViewChild("something") something:ElementRef; 

     ngAfterViewInit(): void {
                this.source = fromEvent(this.something.nativeElement, 'keyup');
                this.source.pipe(debounceTime(1200)).subscribe(c => 
                {
                          list = list.filter(item => item.label.toLocaleLowerCase().includes(this.searchedKPI.toLocaleLowerCase())).slice();
                }
                );
              }

2 Comments

what is 'this.source' in this context?
@TorstenN. Hello, it's the Subscription object output of the fromEvent(..) function. it can also be used to end the subscription in ngOnDestroy(..) { }` by calling this.source.unsubscribe()whenever we no longer use the actual component to prevent memory leaking issues.
1

This solution works for me

View Template.html

<input type="text" placeholder="Filter..." class="form-control" [(ngModel)]="filter" (input)="searchChange($event.target.value, true)">
<button class="btn btn-primary" type="button" (click)="searchChange(filter, false)"><i class="fa fa-search"></i></button>

Comonent.ts

  filter= '';
  private timer: any;

  searchChange(filter: string, to = false) {
    filter = filter.toLowerCase();

    if (to) {
      clearTimeout(this.timer);

      this.timer = setTimeout(() => {
        this.valuesFilter = this.allValues.filter(f => f.field.toLowerCase().includes(filter));
      }, 400);
    } else {
      this.valuesFilter = this.allValues.filter(f => f.field.toLowerCase().includes(filter));
    }
  }

Comments

-1

cant we use timeout function?

(keyup)="keyupFunc()" --> html
keyup() {
       timeout((your function code), delay_time_you_need);
   } --> ts

1 Comment

this solution is not working when keyup() happens multiple at the same time.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.