I'm building an autocomplete function that uses the user's input to filter a set of meals as they type:
export class MealAutocompleteComponent {
mealCtrl = new FormControl()
filteredMeals: Observable<Array<Meal>>
liveMeals$: Observable<Array<Meal>>
mealsSnapshot: Meal[]
constructor(private mealsQuery: MealsQuery) {
this.liveMeals$ = this.mealsQuery.all$ // <= observable (not used)
this.mealsSnapshot= this.mealsQuery.getAll() // <= array (used)
// Observe the user input and trigger filtering
this.filteredMeals = this.mealCtrl.valueChanges.pipe(
startWith(null),
map((filterTerm: string | null) => {
let mealArr: Array<Meal> = mealsQuery.getAll() // <= I'd like to use observable instead
return filterTerm ? this._filter(filterTerm, mealArr) : mealArr
})
)
}
private _filter(value: string, meals:Array<Meal>): Array<Meal> {
// Method for filtering meals
const filterValue = value.toLowerCase()
return meals.filter(meal =>
meal.label.toLowerCase().indexOf(filterValue) === 0
)
}
}
How can I switch from using meals:Array to meals:Observable?
The code above all works as intended. However there are two places that we can get the overall list of meals
from - an array this.mealsSnapshot
, and an observable: this.liveMeals
.
I've written the code above using the mealsSnapshot
array. However I would prefer to use the liveMeals$
observable since, for various reasons, it offers more flexibility (and is drawn from a state store). But I've absolutely no idea what the correct RxJS operators are to do this. The liveMeals$
observable is an observable that returns a single array of meals.
I've tried something like this but a) it's got subscribers inside subscribes which I know is not the RxJS way and b) it doesn't work c) it looks a mess
this.filteredMeals = this.mealCtrl.valueChanges.pipe(
startWith(null),
concatMap((filterTerm: string | null) => {
this.liveMeals$.pipe(
first()
).subscribe((mealsArr:Meal) => {
return filterTerm ? this._filter(filterTerm, mealsArr) : mealsArr
}
)
})
)
What would be the correct way to use liveMeals$:Observable<Array>
rather than the mealsSnapshot
?