Tom Rudge
Tom Rudge

Reputation: 3272

Pipe to allow multiple filter values simultaneously - Angular

Buttons are generated using *ngFor bringing back as many different types of values available to filter by. I'm filtering on a key of 'location', therefore if there are locations of 'west' and 'england' then two buttons of 'west' and 'england' are available to filter by.

What I want to be able to do is select more than one filter. If I click 'england' all the results for 'england' come back, then if I click 'west' then 'west' comes back as well as 'england' still being "active". Currently, I can only click one filter at a time.

I think I need to assign an active class to my button then this will push an array of whats active to send to my pipe to do the filtering... ?

My filter Button

  <div ngDefaultControl [(ngModel)]="filteredLocation" name="locationFilter" id="locationFilter">
    <button value="All" class="m-2 btn btn-primary" type="button">All</button>
    <button [class.active]="selectedIndex === i" (click)="filteredLocation = entry.location" class="m-2 btn btn-primary" type="button" *ngFor="let entry of timeLine | filterUnique; let i = index">{{entry.location}}</button>
  </div>

single filter on results

<div class="timeline">
  <my-timeline-entry *ngFor="let entry of timeLine | filter:filteredLocation:'location'" timeEntryHeader={{entry.year}} timeEntryContent={{entry.detail}} timeEntryPlace={{entry.place}} timeEntryLocation={{entry.location}}></my-timeline-entry>
</div>

I have created a stackBlitz of what I've got - try clicking on a filter you will see only one filter can be applied at one time. https://stackblitz.com/edit/timeline-angular-7-nve3zw

Any help here would be awesome. Thanks

Upvotes: 0

Views: 761

Answers (1)

jitender
jitender

Reputation: 10429

There can be multiple ways to do that one would be to attach some property to determine if location is active for example isLocationActive

Then toggle this flag as per your need and to apply active class also you don't need filter pipe in that case

So your html will look like

<div class="form-group row">
  <div ngDefaultControl [(ngModel)]="filteredLocation" name="locationFilter" id="locationFilter">
        <button value="All" class="m-2 btn btn-primary" (click)="activeAllEntries()" type="button">All</button>
        <button [class.active]="entry.isLocationActive" (click)="entry.isLocationActive = !entry.isLocationActive" class="m-2 btn btn-primary" type="button" *ngFor="let entry of timeLine | filterUnique; let i = index">{{entry.location}}</button>
      </div>
</div>

<div class="timeline">
  <ng-container *ngFor="let entry of timeLine">
<my-timeline-entry *ngIf="entry.isLocationActive" timeEntryHeader={{entry.year}} timeEntryContent={{entry.detail}} timeEntryPlace={{entry.place}} timeEntryLocation={{entry.location}}></my-timeline-entry>
  </ng-container>

</div>

TS function

   activeAllEntries() {
      this.timeLine.forEach(t=> t.isLocationActive=!t.isLocationActive)
   }

working Demo

Upvotes: 1

Related Questions