rxjs объединяет и фильтрует наблюдаемую информацию на основе значений из другой наблюдаемой - PullRequest
0 голосов
/ 28 августа 2018

Как мне отфильтровать наблюдаемую, используя значения из другой наблюдаемой, как внутреннее соединение в SQL?

class Item {
    constructor(public name: string public category: string) {
    }
}

class NavItem {
    constructor(public key: string public isSelected: boolean = false) {
    }
}

// Build a list of items
let items = of(new Item('Test', 'Cat1'), new Item('Test2', 'Cat2'))
            .pipe(toArray());

// Determine the unique categories present in all the items
let navItems = from(items)
               .pipe(mergeAll(),
                     distinct((i:item) => i.category),
                     map(i=>new NavItem(i.category)),
                     toArray());

Я строю многогранный поиск, поэтому предположим, что в пользовательском интерфейсе выбран NavItem "Cat1", поэтому я хочу создать наблюдаемый из всех элементов, которые имеют эту категорию. После фильтрации до выбранного NavItem я не уверен, как ввести элементы, отфильтровать их и выплюнуть только те элементы, которые относятся к выбранной категории. Вот что у меня есть:

let filteredItems = navItems.pipe(
   mergeAll(),
   filter(n => n.isSelected))
   // join to items?
   // emit only items that match a selected category?

Ожидаемый результат будет

[{name: 'Test', category: 'Cat1'}]

Ответы [ 2 ]

0 голосов
/ 30 сентября 2018

Я наконец-то вернулся к рассмотрению этого и выяснил, как это решить. Мне нужно было использовать switchMap, чтобы объединить наблюдаемые вместе в одном контексте. Затем я могу использовать карту для испускания всех соответствующих предметов:

let filteredItems = from(items)
   .pipe(mergeAll(),
         switchMap((i) => navItems
              // Get only navItems that are selected
             .pipe(filter(ni => ni.isSelected),
                   // Convert back to array so I can if there are any selected items
                   // if zero, then show all items
                   toArray(),
                   map((nav) => {
                     if(nav.lengh > 0) {
                         // If the item's category matches, return it
                         return nav.some(x => x.key == i.category) ? i : null;
                     }

                     // If no categories were selected, then show all 
                     return i;
                   })
             }),
           // Filter out the irrelevant items
           filter(x => x !== null),
           toArray()
     );              
0 голосов
/ 28 августа 2018

Если я правильно понимаю, вы хотите выбрать определенный navItem, представляющий определенную категорию, а затем выбрать все items, которые имеют такую ​​категорию.

Если это так, чем вы можете создать такую ​​функцию или метод, как этот

selectedItems(categoryId) {
   return items.pipe(filter(item => item.category === categoryId));
}

Как только вы нажмете navItem, вы создадите событие, которое ссылается на navItem и, следовательно, интересующий вас идентификатор категории. Затем вам нужно вызвать функцию selectedItems и передать выбранный вами идентификатор категории. Это вернет Observable, который испускает все предметы выбранной вами категории.

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