0
votes

I have follow structure:

  • Main component (renders items via item-service)
    • Panel component (contains searching components)
      • SerachByTitle component (contains input field for title items)
      • SerachBySomething component (contains something input field for something items)
  • Item service

I want to render items (which fit search-request) within Main-component when user inputs title within SerachByTitle-component.

For this purpose I used EventEmitter: Panel-component, SerachByTitle-component and SerachBySomething-component have decorator @Output.

SerachByTitle and SerachBySomething pass data to Panel-component, and Panel-component forms single object-params, and then passes to Main-component.

I ran into a problem when user inputs title - after each keyup Main-component re-render items. I tried to use combination: debounceTime(timeDelay), distinctUntilChanged(), switchMap(), but it don't help me.

What am I doing wrong?

Sorry for my bad English :(

UPD: For understanding my situation I added example. For main-component I used combination: debounceTime(), distinctUntilChanged(), switchMap(). But delay for search does not exist.

1
Can you produce some code you worked on, as base for us to help you on a specific example ?Exomus
Exomus, thank you! I added link to stackblitzQuestionMan

1 Answers

2
votes

Here is your code (main.component.ts):

searchChangedHandler(filter){
  this.itemService.searchItems(filter).pipe(
      debounceTime(1300),
      distinctUntilChanged(),
      switchMap((items) => this.listItems = items),
    ).subscribe();
}

The problem is that you apply debounceTime+distinctUntilChanged in an incorrect place. Here is a simplified diagram of what is happening in your project:

      #1                   #2                       #3                                
oninput event ---> ItemService.search(term) ----> of(items) ---> ...

                           #4                                      #5
... ---> pipe(debounceTime(1300)+distinctUntilChanged) ---> this.listItems = items 

Basically you run search on every keystroke, and then apply debounceTime+distinctUntilChanged on the results of the search. Which makes little sense, because you apparently want to limit the number of requests going to your ItemService, so you have to apply debounceTime before calling ItemService

(You may wonder why you don't see the 1300 delay getting applied even to the results of ItemService.search, and you see changes immediately. The reason is that of(items) on the step #3 on the above diagram creates a new observable that completes immediately, so the delay is not applied).

So here is the correct way to handle this:

oninput event ---> pipe(debounceTime(1300)+distinctUntilChanged) ----> ...

... ----> ItemService.search(term) ----> this.listItems = items 
  private searchStream = new Subject<any>();

  ngOnInit() {
    this.searchStream
      .pipe(
        debounceTime(1300),
        distinctUntilChanged(),
        switchMap(filter => this.itemService.searchItems(filter))
      )
      .subscribe(items => this.listItems = items);
  }

  searchChangedHandler(filter){
    this.searchStream.next(filter);
  }

Here is the corrected project: https://stackblitz.com/edit/angular-iopeep