I'm building with Angular and have used a filter pipe to filter on the selected option from my dropdown on the *ngFor
loop. The content then filters accordingly. I want to swap the select options to buttons or pills. So when a button is clicked the filter takes place - the button will act as a on/off switch so you can have more than one option filtered.
Here is my stackblitz example - https://stackblitz.com/edit/timeline-angular-7-tyle1f
<div class="form-group row">
<div class="col-sm">
<select class="form-control" name="locationFilter" id="locationFilter" [(ngModel)]="filteredLocation">
<option value="All">All</option>
<option *ngFor="let entry of timeLine | filterUnique" value="{{entry.location}}">{{entry.location}}
</option>
</select>
</div>
//Button filters below
<div ngDefaultControl [(ngModel)]="filteredLocation" name="locationFilter" id="locationFilter">
<button class="btn btn-primary" type="button" *ngFor="let entry of timeLine | filterUnique">{{entry.location}}</button>
</div>
</div>
I'm not sure how to get the buttons to work the same way as no filtering takes place.... any help appreciated!?
Bind a click event (click)="filteredLocation = entry.location"
to the button
Try like this:
<div ngDefaultControl [(ngModel)]="filteredLocation" name="locationFilter" id="locationFilter">
<button (click)="filteredLocation = entry.location" class="btn btn-primary" type="button" *ngFor="let entry of timeLine | filterUnique">{{entry.location}}</button>
</div>
Working Demo
The crux of this is just assign the value of the button/switch to your filteredLocation
variable like below
<button (click)="filteredLocation = entry.location" class="btn btn-primary" type="button" *ngFor="let entry of timeLine | filterUnique">{{entry.location}}</button>
Updated Demo
Hope this helps :)
Easier to just have a click handler:
<div>
<button class="btn btn-primary" type="button" *ngFor="let entry of timeLine | filterUnique" (click)="filter(entry)">{{entry.location}}</button>
</div>
filter(entry) {
this.filteredLocation = entry.location;
}
Demo: https://stackblitz.com/edit/timeline-angular-7-z2e6zh?file=src/app/timeline/timeline.component.ts
If you want to filter on multiple options your filter pipe will have to be adjusted to accomadate an array of strings to filter on.
So in your FilterPipe
the transform function gets changed as follows:
transform(value: string[], filterStrings: string[], propName: string): any {
if (value.length === 0 || !filterStrings || filterStrings.length === 0) {
return undefined;
}
const resultArray = [];
for (const item of value) {
if (filterStrings.indexOf(item[propName]) >= 0) {
resultArray.push(item)
}
}
return resultArray;
}
After that you need to add some code to the timeline.component.ts
file:
An array to hold all the active filter options:
filteredLocations: string[] = [];
A function to toggle an option on or off:
toggle(location) {
let indexLocation = this.filteredLocations.indexOf(location);
if (indexLocation >= 0) {
this.filteredLocations = this.filteredLocations.filter((i) => i !== location);
} else {
this.filteredLocations.push(location);
}
}
Now change the template (timeline.component.html
):
Remove the selection box.
Add a click handler to your button:
<button (click)="toggle(entry.location)" class="btn btn-primary" type="button" *ngFor="let entry of timeLine | filterUnique">{{entry.location}}</button>
Lastly, the filter should accept the new filtered locations: (I just changed filteredLocation to filteredLocations)
*ngFor="let entry of timeLine | filter:filteredLocations:'location'"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With