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 !

14
  • can you specify whether the checkbox is multi select or single select (act as radio button) ? Commented Jun 5, 2019 at 8:52
  • please specify if you want to filter by one value of status or multiple value at a time ? Commented Jun 5, 2019 at 9:10
  • Are you using Third Party Library for filter? or have written own method? Commented Jun 5, 2019 at 9: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. Commented Jun 5, 2019 at 9:42
  • @PrashantPimpale Actually i'm using ng2-search-filter package but it seems this package only work for a search bar Commented Jun 5, 2019 at 9:44

1 Answer 1

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;
  }
 }

}
Sign up to request clarification or add additional context in comments.

11 Comments

Got an error when I check : ERROR TypeError: "term.toLowerCase is not a function"
@StevePiron updated the answer , please check it. (changes to html, ts code and search pipe)
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 :/
@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
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.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.