4

I'm currently stuck on a problem with angular. I try to filter an object array using checkbox but it doesn't work. I would try to filter my array by status.

I already try to use "ng-true-value" when i check the checkbox but it seems it doesn't work because of my object array.


mockdata.service.ts :

export class MockDataService {
  House: Array<object> = [];

  constructor() {}

  getHouse() {
    let options = {min:100, max:500}
    const types = ["Maison","Appartement","Bureau","Batiment publique"];
    const status = ["En cours","Prêt à publier","Déjà publié","Informations manquantes"];
    // const status = [1,2,3,4,5];
    for (let i = 0; i < 1; i++) {
      const randomTypes = Math.floor(Math.random()*types.length);
      const randomStatus = Math.floor(Math.random()*status.length);
      this.House.push({
        id: faker.random.uuid(),
        owner: faker.company.companyName(),
        username: faker.internet.userName(),
        street: faker.address.streetAddress(),
        city: faker.address.city(),
        garden: faker.random.number(),
        img: faker.image.city(),
        surface: faker.random.number(options),
        title: faker.lorem.word(),
        type: types[randomTypes],
        projectStatus: status[randomStatus],
        date: faker.date.recent(10)
      });
    }

    return of(this.House);
  }

project-list.component.html :

<input type="checkbox" name="checkbox" [(ngModel)]="checkboxStatus" ng-true-value="'En cours'" ng-false-value="''">
<tr *ngFor="let information of House | filter:searchText | filter:checkboxStatus">

I would like to have 3 checkboxes and when I check a checkbox, the object array displayed as a list should filter by this checkbox.

Thanks for your help !

Beda
  • 107
  • 1
  • 11
  • can you specify whether the checkbox is multi select or single select (act as radio button) ? – Joel Joseph Jun 05 '19 at 08:52
  • please specify if you want to filter by one value of status or multiple value at a time ? – Joel Joseph Jun 05 '19 at 09:10
  • Are you using Third Party Library for filter? or have written own method? – Prashant Pimpale Jun 05 '19 at 09:33
  • @JoelJoseph the checkbox is single select, i would like to have a checkbox for each status I have. If I have "In progress" status and then click on the "In progress" checkbox, it should display only the project with this status. – Beda Jun 05 '19 at 09:42
  • @PrashantPimpale Actually i'm using ng2-search-filter package but it seems this package only work for a search bar – Beda Jun 05 '19 at 09:44
  • @StevePiron Do you want multiple filters? Can you provide Stackblitz code? – Prashant Pimpale Jun 05 '19 at 09:58
  • @StevePiron please check the following answer for single select, if you want multi select then you will have to change it to retrieve the selected checkbox value on `(change)` event and also have to make some changes to filter pipe logic – Joel Joseph Jun 05 '19 at 10:04
  • @JoelJoseph got an error when I check – Beda Jun 05 '19 at 10:15
  • @PrashantPimpale I'll try to do that – Beda Jun 05 '19 at 10:15
  • @JoelJoseph Hello ! I try to do the multiselect as you said in comment before but I don't know how make it works, could you please help me again ? – Beda Jun 12 '19 at 12:52
  • @StevePiron updated my answer , please check the same – Joel Joseph Jun 13 '19 at 10:18
  • @JoelJoseph Thanks for the update. unfortunately, there is always an error with toLowerCase(), I don't understand why – Beda Jun 13 '19 at 10:52
  • @StevePiron can post the error message shown – Joel Joseph Jun 13 '19 at 11:05
  • @JoelJoseph This is the error : PageProjectsListComponent.html:46 ERROR TypeError: term.toLowerCase is not a function – Beda Jun 13 '19 at 11:34

1 Answers1

1

You can do that in the following way :


if you want Single-select


something.component.html

    <input type="checkbox" id="ckb" (change)="onCheck($event,'En cours')"  name="En_cours" value="En cours">
    <tr *ngFor="let information of House | search: searchText | filter: filterKey">

something.component.ts

filterKey: string = '';
searchKeyWord: string = '';
onCheck(event,$value){
  if ( event.target.checked ) {
     this.filterKey= $value;
  }
  else
  {
     this.filterKey= '';
  }
}

search.pipe.ts

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

@Pipe({
  name: 'search'
})
export class SearchPipe implements PipeTransform {

  transform(items: any, term: any): any {
    if (term === undefined) return items;

    return items.filter(function(item) {
      for(let property in item){

        if (item[property] === null){
          continue;
        }
        if(item[property].toString().toLowerCase().includes(term.toString().toLowerCase())){
          return true;
        }

       }
      return false;
    });
  }

}

filter.pipe.ts

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

@Pipe({
  name: 'filter'
})

export class FilterPipe implements PipeTransform {
  transform(items: any[], filterText: string): any[] {
    if(!items) return [];
    if(!filterText) return items;
filterText = filterText.toLowerCase();
return items.filter( it => {
      return it['projectStatus'].toString().toLowerCase().includes(filterText);
    });
   }

}

If Multi-Select then make few changes to above code :


something.component.html

 <input type="checkbox" id="ckb" (change)="onCheck($event,'En cours')"  name="En_cours" value="En cours">
 <tr *ngFor="let information of House | search: searchText | filter: filterKeys">

something.component.ts

filterKeys = [];
searchKeyWord: string = '';
onCheck(event,$value){
  if ( event.target.checked ) {
     this.filterKeys.push($value);
  }
  else
  {
     this.filterKeys.splice(this.filterKeys.indexOf($value), 1);
  }
}

filter.pipe.ts

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

@Pipe({
  name: 'filter'
})

export class FilterPipe implements PipeTransform {
  transform(array: any[], query:string[]):any[] {
  if (typeof array === 'object') {
   var resultArray = [];
   if (query.length === 0) {
     resultArray = array;
   }
   else {
     resultArray = (array.filter(function (a) {
      return ~this.indexOf(a.projectStatus);
    }, query));
   }
   return resultArray;
 }
 else {
  return null;
  }
 }

}
Joel Joseph
  • 5,889
  • 4
  • 31
  • 36
  • Got an error when I check : ERROR TypeError: "term.toLowerCase is not a function" – Beda Jun 05 '19 at 10:14
  • @StevePiron updated the answer , please check it. (changes to html, ts code and search pipe) – Joel Joseph Jun 05 '19 at 10:39
  • Someone can explain me how I can use this to multiselect instead of single select ? I'm stuck and I'm a beginner with Angular :/ – Beda Jun 13 '19 at 09:35
  • @StevePiron you just need to change the above code a bit `filterKeys = [];` then in on check function if checked then `this.filterKeys.push($value)` else `this.filterKeys.splice(this.filterKeys.indexOf($value), 1);` now you have all selected values in the array so change the filter pipe code accordingly and then pass the `| filter: filterKeys"` in the template instead of `filterkey` – Joel Joseph Jun 13 '19 at 10:03
  • Well, that's the logic I had considered for the "onCheck" function, thank you. Now I have to find the solution for the pipe. I guess I already have to modify the type of filterText and remove the toLowerCase that gives me an error. Anyway, thank you for your help, it's quite tedious to start Angular. – Beda Jun 13 '19 at 10:31
  • @StevePiron you can solve the `toLowerCase()` problem by just adding `.toString()` before it to make sure that it is string and you can perform `.toLowerCase()` on it – Joel Joseph Jun 13 '19 at 11:08
  • @StevePiron also make sure you have replaced `filterKey` with `filterKeys` in template `` – Joel Joseph Jun 13 '19 at 11:19
  • I'll try with the toString() and yes I replaced with filterKeys – Beda Jun 13 '19 at 11:35
  • Is it possible the error came from search.pipe? Or this line ```transform(array[], query:string[]):any[]``` ? VSCode tells me he expected "," just after ```array[``` – Beda Jun 13 '19 at 11:43
  • @StevePiron sorry about that it was a typo , it should have been `array: any[]` now i have updated it in answer – Joel Joseph Jun 13 '19 at 12:40
  • Oh yeah no more errors now, but filter using checkbox doesn't work anymore – Beda Jun 13 '19 at 14:38