Фильтровать массив вложенных объектов - Observable - PullRequest
0 голосов
/ 15 марта 2019

У меня есть наблюдаемая из массива, который содержит объекты объекта.(как показано на рисунке).У меня есть observable, который получает эти значения из запроса get, а затем у меня есть еще один observable для хранения отфильтрованных значений.У меня есть переменная searchText от binded до input, и я вызываю функцию каждый раз, когда изменяется входной сигнал.

 <input name="problem-search" [(ngModel)]="searchText" matInput placeholder="Search for problems..." (input)="filterProblems()">

До сих пор я пробовал это, но это не дает желаемого результата.Это иногда фильтрует, но это случайно, и это даже не относится к searchInput.Честно говоря, я даже не знаю, как у меня получается.Rxjs может иногда сбивать с толку.Пожалуйста, дайте мне знать, что я делаю здесь неправильно. enter image description here

    filterProblems() {
    if (this.searchText === '') {
      this._filteredProblems$ = this._everyProblem$;
    }

    this._filteredProblems$ = this._everyProblem$.pipe(
      map(data => data),
      tap(ele => ele.filter(data => {
        Object.keys(data).forEach(key => {
          if (data[key].name.toLowerCase().includes(this.searchText)) {
            delete data[key];
          }
        });
      }))
    );

    this._filteredProblems$.subscribe(data => console.log(data))
  }

1 Ответ

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

Оператор tap должен использоваться для побочных эффектов и не должен быть операцией изменения потока.Использование оператора map таким способом на самом деле ничего не делает для вас.Я думаю, что вы должны вернуть отфильтрованный объект из чего-то вроде операторов стиля map, чтобы изменить то, что возвращает поток, но не исходный объект, который испускается.В настоящее время весь объект возвращается в поток, за исключением ключей, которые вы из него удаляете.После удаления похоже, что они удаляются из оригинала.

Использование Object.keys - это один из способов перебора объектов, но в этом случае вы можете сохранить шаг с помощью Object.values и вместо этого потяните нужную клавишу.

Что-то вроде этого должно быть близко к тому, что вам нужно:

map((data: yourType[]) =>
  data.filter((item: yourType) =>
    (!this.searchText || !Object.values(item)[0].name.toLowerCase().includes(this.searchText))
),
  • Возвращение результата из данных.Фильтр даст вам пустой массив, по крайней мере, при условии, что исходные данные являются хотя бы пустым массивом.
  • Инвертирование флэш-значения для searchText вернет все элементы
  • Возвращает Object.valuesсписок объектов из guid
  • [0] вернет первый (должен быть только один)
  • При возврате инверсии включений сохранятся элементы, которые не содержат поисковый текст

В качестве альтернативы, вы можете настроить запускающие потоки для наблюдения за изменением источника данных или входа.- Поместите searchText в BehaviorSubject, чтобы вы могли использовать его для запуска изменений в потоке.- Объединить наблюдаемый searchText и наблюдаемый _everyProblem $ с CombatLatest и установить результат, равный _filteredProblems $ - Применить аналогичный фильтр внутри, а также debounce

Может быть что-то вроде этого, чтобы вызвать некоторые мысли:

this._filteredProblems$ = combineLatest(
  this.searchTextSubject.asObservable(),
  this._everyProblem$,
).pipe(
  debounce(() => timer(50))
  map((searchText: string, data: yourType[]) =>
    data.filter((item: yourType) =>
      (!searchText || !Object.values(item)[0].name.toLowerCase().includes(searchText))
  ),
);
...