Угловой асинхронный канал не обновляет результат после фильтрации входного массива - PullRequest
1 голос
/ 19 марта 2019

В родительском компоненте у меня есть поток Tour [] tours_filtered: Observable<Tour[]>, который я назначаю в функции подписки http-запроса

this.api.getTours().subscribe(
  result => {
    this.tours_filtered = of(result.tours);
  }
)

в представлении, отображающем поток с использованием асинхронного канала

<app-tour-box [tour]="tour" *ngFor="let tour of tours_filtered | async"></app-tour-box>

До сих пор все работает как положено.В дочернем компоненте у меня есть входной текст, который испускает введенное пользователем значение для фильтрации массива Tour по заголовку.

В родительском компоненте, который я прослушиваю для значений, выданных в функции, я переключаюсь на новый поток Tour [], отфильтрованный по этому значению, используя switchMap

onSearchTitle(term: string) {
  this.tours_filtered.pipe(
    switchMap( 
      (tours) => of( tours.filter((tour) => tour.name.toLowerCase().includes(term)) )
    )
  )
}

Я думал, что асинхронный каналпостоянно слушал, чтобы отразить изменения в массиве, к которому он был применен, и поэтому я подумал, что мне не нужно подписываться в функции выше, но ничего не изменилось в представлении, когда я ввожу данные для фильтрации результатов.

Результаты обновляются корректно, если я назначаю новый поток исходному массиву в функции подписки


    onSearchTitle(term: string) {
        this.tours_filtered.pipe(
          switchMap((tours) => of(tours.filter((tour) => tour.name.toLowerCase().includes(term))))
        ).<b>subscribe( val => { this.tours_filtered = of(val); })</b>
      }

Правильна ли эта процедура?Могу ли я избежать подписки, потому что я уже использую асинхронный канал?Есть лучший способ достичь моей цели?

РЕДАКТИРОВАНИЕ:

Может быть, я нашел решение, мне нужно переадресовать новый поток для переменной, как это

onSearchTitle(term: string) {
    this.tours_filtered = of(this.city.tours).pipe(
      switchMap((tours) => of(tours.filter((tour) => tour.name.toLowerCase().includes(term))))
    );
  }

и мне не нужно снова подписываться, результаты в представлении изменяются в соответствии с поисковым запросом, введенным пользователем.Это правильный путь?

1 Ответ

0 голосов
/ 19 марта 2019

Я думаю, что в вашей ситуации решение должно работать следующим образом:

onSearchTitle(term: string) {
  this._searchTerm = term;
  this.tours_filtered = of( 
    this.city.tours.filter((tour) => tour.name.toLowerCase().includes(term))
  )
}

Потому что в вашем примере вы не меняете наблюдаемое, которое используется в ngFor. Таким образом, это не работает.

Однако я не вижу причины использования наблюдаемых здесь, если только это не первый шаг и вы не собираетесь получать эти данные с сервера в будущем


UPDATE

Лучшим решением для вас будет рассмотреть ваш вклад как наблюдаемый и следить за изменениями:

// your.component.ts
export class AppComponent  {

  searchTerm$ = new BehaviorSubject<string>('');
  results = this.search(this.searchTerm$);

  search(terms: Observable<string>) {
    return terms
      .pipe(
        debounceTime(400),
        distinctUntilChanged(),
        switchMap(term => {
          return of(this.city.tours.filter((tour) => tour.name.toLowerCase().includes(term)))
        }
        )
      )
  }

}
// your.template.html
...
<input type="" (input)="searchTerm$.next($event.target.value)">
...

Кроме того, было бы замечательно добавить debounceTime и distinctUntilChanged для улучшения взаимодействия с пользователем и уменьшения количества поисковых запросов.

Подробнее см. . Также, пожалуйста, обратитесь к этой статье для более подробных объяснений

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...