Tenzolinho
Tenzolinho

Reputation: 982

Angular 6 checkbox filter overrides previous checkbox

I am trying to build a filter using checkboxes. Down below is a snippet of my code:

filter.pipe.ts

import { Pipe, PipeTransform, Injectable } from '@angular/core';

@Pipe({
  name: 'filter2'
})
@Injectable()
export class FilterPipe implements PipeTransform {
  transform(items: any[], field: string, value: string): any[] {
    if (!items) {
      return [];
    }
    if (!field || !value) {
      return items;
    }

    var newArray = [];
    items.filter(singleItem => {
      if (singleItem != null && singleItem[field] != null && singleItem[field] != undefined && singleItem[field].includes(value)) {
        newArray.push(singleItem);
      }
    })
    return newArray;
  }
}

app.html

<ng-container *ngFor="let group of groups;  let i=index">
     <label class="btn btn-filter" id="bttns">
            <input type="checkbox" name="customersGroupFilter" autoComplete="off" [value]="group" (change)="changeGroup($event)">
                      {{ group }}
     </label>&nbsp;
 </ng-container>

.....

 <tr *ngFor="let user of usersList | filter2: 'group' : groupValue">

.....

app.ts

groups = ['a', 'b', c']
usersList = [{'name': 'john', 'group': 'a'}, {'name': 'mike', 'group': 'a'}, {'name': 'doe', 'group': 'b'}, {'name': 'tim', 'group': 'c'}]
groupValue

changeGroup(event) {
    this.groupValue = event.target.value
}

This works fine, but if I want to make multiple checks, the new checkbox value will always override my previous value, so multicheck won't be possible.

eg.:

if I check group 'a' => it will return me john, mike

if I check 'a' and 'b' => it will return me only doe

How can I modify my code to achieve what I want? Thank you for your time!

Upvotes: 0

Views: 408

Answers (2)

YGLin
YGLin

Reputation: 74

Here is a working example if you really want to use Angular Pipe https://stackblitz.com/edit/angular-qw7kkf

  1. You need to change your transform function in Pipe to support multiple group values

    transform(items: any[], field: string, value: string[]): any[] {
    if (!items) {
      return [];
    }
    if (!field || !value || value.length <= 0) {
      return items;
    }
    return items.filter(singleItem => {
      return (singleItem != null && singleItem[field] != null && singleItem[field] != undefined && value.indexOf(singleItem[field]) >= 0);
    });
    

    }

See that the type of value changed from string to string[], and also the usage of Array.filter function

2.Change the type of groupValue from string to string[], too. And this is your new changeGroup() function

changeGroup(event) {
  const group = event.target.value;
  const index = this.groupValue.indexOf(group);
  if ( index < 0) {
    this.groupValue.push(group);
  } else {
    this.groupValue.splice(index, 1);  
  }
  const newGroupValue = [];
  newGroupValue.push.apply(newGroupValue, this.groupValue);
  this.groupValue = newGroupValue;
}

Now to check a group also means trigger it in groupValue. And notice that how cumbersome I have to assign a new array to this.groupValue every time, because if you don't do so, the filter2 Pipe won't detect the change "inside" this.groupValue array. That's also the reason I don't recommend Pipe for your usage scenario, it's a bit over for Angular Pipe.

Upvotes: 1

baao
baao

Reputation: 73241

You are doing some things the wrong way. First, you shouldn't use a filtering pipe. That filter will get called many times per second and will potentially slow down your application. Instead, run the filter function on click of a checkbox.

changeGroup(event) {
    // filter function here
}

The second thing that jumps to my eyes is the misuse of filter. Array.filter() filters the array for you - the if statement must really be the callback's return value

this.newArray =  items.filter(singleItem => 
  singleItem != null && singleItem[field] != null && singleItem[field] != undefined && singleItem[field].includes(value)
)

You can then use newArray...

So your formerly filtered userList becomes

<tr *ngFor="let user of newArray">

Upvotes: 1

Related Questions