Reputation: 57
i'm trying to understand the logic behind using filters in Angular but im finding hard to configure it. I red about dynamic filters but i didn't understand how to use those. I hope you could give me some help.
I have a showcaseComponent where i wish to add three filters (Name, Description, Category) as text-type.
I type something like "Hello" in the Name filter and it shows me all the elements with "Hello" in the name for example.
I didn't find a proper guide that explain me step-by-step how to implement filters.
Upvotes: 0
Views: 1115
Reputation: 57919
Jany. Angular works on observables, so a good approach are always observables. You can think in an observable as a function that return an object or an array in "async mode" (you don't get it also when you subscribe to it)
If you have three "inputs", we began create a FormGroup using ReactiveForms with this
form=new FormGroup({
name:new FormControl(''),
description:new FormControl(''),
category:new FormControl(''),
})
A formGroup have a property that it's an Observable: valueChanges.
Now depend from your data and what are you using. If you use a simple array you can return an observable in this way
myWholeArray=[{...},{....},{...},...]
myArrayObservable$=this.form.valueChanges.pipe(
startWith({name:'',description:'',category:''}),
switchMap(res:any)>={
//here you have an object of type {name:...,description:...,category:...}
//if we have no input any value
if (!res.name && !res.description && !res.catagory)
return of(this.myWholeArray)
//else you filter your array
return of(
this.myWholeArray.filter((x:any)=>{
bool fulfilled=(res.name && x.name.toUpperCase().indexOf(res.name.toUpperCase())
fulfilled=fullfilled && (res.description && x.description .toUpperCase().indexOf(res.description .toUpperCase())
fulfilled=fulfilled && (res.category&& x.category.toUpperCase().indexOf(res.category.toUpperCase())
return fullfilled;
})
)
}))
As you have an observable you indicate in the .html some like
<div *ngFor="let item of myArrayObservable$|async>
{{item.name}} {{item.description}} {{item.category}}
</div>
Yes, I know I was too much quickly. So step by step
When we have an observable we can makes some operations over it. This
"operations" are the rxjs/operators
. This operators get one (or
several) observable and transform in another one and we use using
pipe
and the operators separated by commas, like
observable.pipe(firstOperator(res),secondOperator(res),...)
The first operator is startWith
. One observable only show the value
is you subscribe to it. Yo can subscribe explicitaly (by code using
subscribe
) or using the async pipe. As we want use this
observable, we "initialize" giving an initial value.
The second operator is switchMap
. switchMap transform one
observable in another. So we transform the "valueChanges" in another
observable. We need import this two operators import {startWith,switchMap} from 'rxjs/operators'
See that we need return an observable, so it's not valid return an
array. To return an observable when we have an object or an array we
use the third operator of
(as is an creation operator, we need
import {of} from 'rxjs'
)
Well. If you're using material and MatTableDataSource, the "property" filter makes the most part of work form you. See, e.g. this SO
You create the form and subscribe to valuesChanges
this.form.valueChanges.subscribe((res) => {
this.dataSource.filter = JSON.stringify(res);
});
And create a custom function
Upvotes: 1