Ваш главный вопрос о том, как изменить состояние в rx js (добавить, удалить, изменить значение, ...). Это может быть достигнуто с помощью оператора scan .
Дополнительная информация: в последующем сканировании мы используем 1. параметр (accumulator
) как oldOptions/state
и 2. param (value
) как функция (fn
), которая получает oldOptions/state
, возвращает новое / обновленное состояние.
Шаг 1 - что представляет ваше состояние
state: SelectOptions[];
Шаг 2 - какая мутация может быть сделана в вашем состоянии
- переопределение состояния: в настоящее время, когда this.reportService.getFiltersData (this.fieldNameEnum. AicSuites) переопределяет все ваше состояние. Это происходит в операциях касания со строкой this.selectOptions $ .next (res).
- мутация состояния: вы хотите изменить свое состояние при вызове markAsSelected (). Вы хотите инвертировать значение IsSelected из selectedOptions.
Шаг 3 - создайте функции, которые изменяют состояние, которое вы определили
Вы увидите использования и почему мы построили его, как на шаге 4
- переопределение состояния
function stateOverride (newOptions) {
return function (oldOptions) {
return newOptions;
}
// shorter alternative syntax for the same function:
const stateOverride = (newOptions) => (oldOptions) => newOptions;
function stateMutation (selectedOptions) {
return function (oldOptions) {
// I use the DisplayName to compare the selectedOptions with the oldOptions
const selectedDisplayNames = selectedOptions.map(selectedOption => selectedOption.DisplayName)
/* We map over every option. If this specific option is included in the selectedDisplayNames
we create a new object with all old values but inverted IsSelected.
Otherwise we let the oldOption as it is and do not mutate it.*/
return oldOptions.map(oldOption => selectedDisplayNames.includes(oldOption.DisplayName)
? {...oldOption, ...{IsSelected: !=oldOption.IsSelected}}
: oldOption
}
}
Шаг 4. Используйте оператор сканирования для создания , обновите свое состояние
private newState$ = this.reportService.getFiltersData(this.fieldNameEnum.AicSuites)
private optionsSelect$ = new Subject();
private selection$ = merge(
newState$.pipe(map(v => stateOverride(v)),
optionsSelect$.pipe(map(v => stateMutation(v))
).pipe(
scan((oldOptions, fn) => fn(oldOptions), [])
/* This is why we used this weird function syntax (newOptions) => (oldOptions) => in Step 3.
1. We map the stateOverride/stateMutation to the Observables.
2. Those return itself another function that takes the oldOptions
3. In the scan the second param is now a function that takes the oldOptions and returns the updated state/options.*/
)
function markAsSelected(data): void {
this.optionsSelect$.next(data);
}
К вашему сведению: если вы понимаете этот механизм, вы можете обновить любое состояние в каналах без побочных эффектов таким образом. Если вы понимаете принцип и следуете инструкциям, это будет полезным инструментом для множества различных сценариев использования. Не стесняйтесь спрашивать дополнительную информацию. Я обновляю ответ или могу прокомментировать ниже.