Использование наблюдаемых данных из одного редуктора хранилища ngrx для фильтрации результатов в другом

#angular #ngrx

#angular #ngrx

Вопрос:

мое хранилище ngrx состоит из двух наборов данных: preferenceGroups которые содержат группы выбранных значений предпочтений и stocks :

существует множество preferenceGroups , в одном из двух форматов, группа логических значений или диапазон:

 "preferenceGroups": [
    {
        "name": "Sectors",
        "type": "toggles",
        "preferences": [
            {
                "label": "Sector 1",
                "type": "boolean",
                "value": true
            },
            {
                "label": "Sector 2",
                "type": "boolean",
                "value": true
            }
        ]
    },
    {
        "name": "Exchange",
        "type": "toggles",
        "preferences": [
            {
                "label": "Exchange 1",
                "type": "boolean",
                "value": true
            },
            {
                "label": "Exchange 2",
                "type": "boolean",
                "value": true
            }
        ]
    },
    {
        "name": "Price",
        "type": "price-range",
        "preferences": {
            "label": "Price",
            "type": "currency",
            "value": {
                "minimum": 0,
                "maximum": 999
            }
        }
    },
    ...
]
  

У меня также есть куча запасов, все с одинаковыми полями, обычно они выглядят так:

 "stocks": [
    {
        "state": {
            "accepted": false,
            "rejected": false
        },
        "change": -5.36,
        "changePercent": -0.13,
        "dividend": 12.05,
        "equitySummaryScore": 8,
        "exchange": "Exchange 1",
        "price": 97.10,
        "sector": "Sector 1",
        ...
    },
    ...
]
  

Способ работы моих фильтров заключается в том, что для каждой группы предпочтений я хотел бы рассмотреть любой запас, значение которого соответствует любому из логических фильтров, для которого установлено значение true, а в случае диапазона — любое значение, которое находится в пределах диапазона.

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

 this.stocks = this._store.select('stocks');
this.preferenceGroups = this._store.select('preferenceGroups');
  

что мне нужно сделать, это сохранить отфильтрованные запасы как наблюдаемые, используя данные this.preferenceGroups для фильтрации this.stocks .

this.filteredStocks = [something I can't figure out]

например, единственный указанный мной запас будет совпадать, потому что он имеет "exchange": "Exchange 1" , "sector": "Sector 1" и "price": "97.10"

Ответ №1:

Если у вас есть две наблюдаемые, одна с запасами, другая с вашим фильтром, вам необходимо объединить оба потока. Что вам нужно, так это массив каждого запаса и ваши предпочтения, чтобы знать, можете ли вы их показать. Проверьте следующий код:

 let stocks$ = Rx.Observable.of(["stock1", "stock2", "stock3"]);

let preferences$ = Rx.Observable.of(["preference", "preference2"]);

let combined$ = Rx.Observable.combineLatest(
  stocks$, preferences$, (stocks, preferences) => {
      // implement your filtering logic here and returned the filtered stocks
      return stocks   " "   preferences
  });


combined$.subscribe((val) => console.log(val));
  

При использовании combineLatest вы объединяете две наблюдаемые. Функции, которая передается методу combineLatest, будет присвоено последнее значение из stocks $ observable и последнее из preferences $ observable. Эти наблюдаемые данные поступают из вашего хранилища.

В этой функции вы можете просто реализовать логику фильтрации, как в императивном стиле.

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

Если вы подписываетесь на ваш объединенный $ stream в вашем шаблоне, каждое добавление запаса или добавление предпочтений приведет к обновленному представлению.

Комментарии:

1. отличный ответ @KwintenP, это было именно то, что я искал.

2. Где будет жить приведенный вами пример функции? В новой службе, подобной FilteredStockService или какой-либо другой вычисляемой службе хранения наблюдаемых.

3. По этой логике я бы либо вставил интеллектуальный компонент, чтобы создать поток, и передал его немому компоненту. Или я бы сделал это на уровне абстракции, который мне нравится называть песочницей (читайте о том, что это здесь: blog.brecht.io/A-scalable-angular2-architecture