I have seen some answers to this that apply the filter to the database call. I only need to call the database once but can't work out how to filter the array that is inside the observable returned by Firebase.
I have 2 select boxes with a list of tags. I want to get the whole set of items from Firestore and store it in the items Observable. Then when one of the select boxes changes I want to filter that observable so only the items with those tags are shown.
items: Observable<any[]>;
selectedTag1;
selectedTag2;
filteredItems: Observable<any[]>;
tagName1 = ['', 'TAG1', 'TAG2', 'TAG3', 'TAG4'];
tagName2 = ['', 'TAG5', 'TAG6', 'TAG7',
constructor(db: AngularFirestore) {
this.items = db.collection('items').valueChanges();
}
ngOnInit() {
this.filteredItems = this.items.pipe(
map((arr => arr.filter(item =>
item.tags.some(s => s === this.selectedTag1) &&
item.tags.some(s => s === this.selectedTag2))
)));
}
I get no items at all showing on my template. When I change the selectedTag using the select box. I also get no filtering of the items. Can somebody suggest how I do this correctly. I need the selectBoxes to filter if only one has a value or if both have a value.
HTML
<select [(ngModel)]="selectedTag1">
<option *ngFor="let item of tagName1">{{ item }}</option>
</select>
<select [(ngModel)]="selectedTag2">
<option *ngFor="let item of tagName2">{{ item }}</option>
</select>
<ul>
<li class="text" *ngFor="let item of filteredItems | async">
{{item.name}}
<ul>
<li *ngFor="let tags of item.tags">
{{tags}}
</li>
</ul>
</li>
</ul>
ITEMS
[
{
"name": "Item 1",
"tags": [
"TAG1",
"TAG4",
"TAG5",
"TAG6"
]
},
{
"name": "Item 2",
"tags": [
"TAG2",
"TAG3",
"TAG5",
"TAG7",
]
}
]
I have tried to add a function which runs when the select box is changed.
selectChanges() {
this.filteredItems = this.items.pipe(
map((arr => {
console.log(arr);
console.log(this.selectedTag1);
arr.filter(item => {
console.log(item.tags);
item.tags.some(s => s === this.selectedTag1);} );
})));
}
Yet I am still not getting any filtered results.
As you already guessed, you should not filter when selected tags is undefined or empty. Just tweak your filtering logic as shown below:
filter() {
this.filteredItems = this.items.pipe(
map(arr =>
arr.filter(item => {
// return true if selectedTag1 or selectedTag2 is empty
const matchesForTagName1 = this.selectedTag1
? item.tags.indexOf(this.selectedTag1) >= 0
: true;
const matchesForTagName2 = this.selectedTag2
? item.tags.indexOf(this.selectedTag2) >= 0
: true;
return matchesForTagName1 && matchesForTagName2;
})
)
);
}
You can view the complete example in Stackblitz here .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.