В моем компоненте есть два поля формы. Первый - выбрать priceMin, второй - выбрать priceMax.
Затем у меня есть наблюдаемое, которое я хочу отфильтровать.
export class ListingsComponent implements OnInit {
listings$: Observable<Listing[]>;
filterForm: FormGroup;
constructor(private firestore: FirestoreService, private fb: FormBuilder) {}
get priceMin() {
return this.filterForm.get('priceMin');
}
get priceMax() {
return this.filterForm.get('priceMax');
}
ngOnInit() {
this.filterForm = this.fb.group({
priceMin: [null],
priceMax: [null]
});
this.listings$ = this.firestore.getListings().pipe(
switchMap(listings => {
return merge(
this.priceMin.valueChanges.pipe(
map(priceMin => {
return listings.filter(listing => {
return listing.profile.price.hour >= priceMin;
});
})
),
this.priceMax.valueChanges.pipe(
map(priceMax => {
return listings.filter(listing => {
return listing.profile.price.hour <= priceMax;
});
})
)
);
})
);
}
}
Он работает (я имею в виду отсутствие ошибок), но отфильтрованное наблюдаемое ведет себя странно, и результат не такой, как я ожидал.
На изображении предварительного просмотра:
Объявление 1. Результаты верны, когда я выбираю впервые.
Объявление 2. Затем, когда я меняю minPrice, похоже, он игнорирует maxPrice.
Объявление 3. (Нет в превью img) Затем, когда я меняю maxPrice, он игнорирует minPrice и так далее ...
Что может вызвать такое поведение и как это исправить?
Working code:
this.listings$ = combineLatest(this.priceMin.valueChanges, this.priceMax.valueChanges).pipe(
switchMap(price => {
return this.firestore.getListings().pipe(
map(listings => {
return listings.filter(listing => {
return (
listing.profile.price.hour >= price[0] && listing.profile.price.hour <= price[1]
);
});
})
);
})
);
Наконец, я использовал Behavior Subject для хранения начального значения фильтров.
this.priceMin.valueChanges.pipe(map(value => this.filterPriceMin.next(value))).subscribe();
const filters$ = combineLatest(
this.filterPriceMin, // filter 0
this.filterPriceMax // filter 1
);





Проблема не в вашем filter, потому что это просто Array.filter(), и я не вижу в нем ничего плохого.
Вероятно проблема в операторе merge. merge будет излучать, если один из дочерних Observables излучает. E.x: priceMin излучает, затем излучает merge, затем излучает priceMax, затем merge излучает значение priceMax.
Чтобы получить оба значения при излучении наблюдаемого, вы можете изменить merge на combineLatest. Не забудьте немного изменить свою логику, потому что combineLatest возвращает [valueFromObs1, valueFromObs2] как Array, в отличие от merge.
Спасибо за подсказку. Тогда я попробую с combineLatest и дам вам знать.
Ага, наверное, другой map после combineLatest сделает это;)
ОК. Кажется, сейчас работает. Я обновил свой вопрос ответом. Спасибо :)
Единственная проблема с рабочим кодом заключается в том, что он не будет отображать никаких элементов, пока оба наблюдаемых объекта в combLatest не выдадут значение. Но это не часть этого вопроса.