Observable и EventEmitter для передачи данных родителям (Angular) - PullRequest
0 голосов
/ 01 октября 2019

У меня следующая структура:

  • Основной компонент (отображает элементы через item-service)
    • Компонент панели (содержит компоненты поиска)
      • Компонент SerachByTitle (содержитполе ввода для элементов заголовка)
      • Компонент SerachBySomething (содержит что-то для ввода элементов чего-либо)
  • Служба элементов

Я хочу отображать элементы (которые соответствуют запросу поиска) в компоненте Main, когда пользователь вводит заголовок в компоненте SerachByTitle.

Для этой цели я использовал EventEmitter: Panel-component, SerachByTitle-component и SerachBySomething-компонент имеет декоратор @ Output.

SerachByTitle и SerachBySomething передают данные компоненту Panel, а компонент Panel формирует один объект-параметр, а затем передает компоненту Main.

Я столкнулся спроблема, когда пользователь вводит заголовок - после каждого keyup Main-компонент повторно отображает элементы. Я пытался использовать комбинацию: debounceTime (timeDelay), differentUntilChanged (), switchMap (), но это мне не помогло.

Что я делаю не так?

Извините за мой плохой английский: (* ​​1031 *

UPD: Для понимания моей ситуации я добавил пример . Для основного компонента я использовал комбинацию: debounceTime (), DifferentUntilChanged (), switchMap() . Но задержки для поиска не существует.

1 Ответ

1 голос
/ 03 октября 2019

Вот ваш код (main.component.ts):

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

Проблема в том, что вы применяете debounceTime + diverUntilChanged в неверном месте. Вот упрощенная схема того, что происходит в вашем проекте:

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

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

По сути, вы запускаете поиск при каждом нажатии клавиши, а затем применяете debounceTime + diverUntilChanged к результатам поиска. Это не имеет особого смысла, потому что вы, очевидно, хотите ограничить количество запросов, поступающих на ваш ItemService, поэтому вы должны применить debounceTime перед вызовом ItemService

(Вы можете задаться вопросом, почему вы не видите применения задержки 1300даже к результатам ItemService.search, и вы сразу увидите изменения. Причина в том, что of(items) на шаге № 3 на приведенной выше диаграмме создает новую наблюдаемую, которая завершается немедленно, поэтому задержка не применяется).

Итак, вот правильный способ справиться с этим:

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);
  }

Вот исправленный проект: https://stackblitz.com/edit/angular-iopeep

...