Steve020
Steve020

Reputation: 134

Angular 7 Custom Pipe that returns search text along with item Count

I have a search feature for a table that uses a custom filter pipe. It returns the text correctly. However I need to also be able to return the count of Items after the filter has been applied.

I need to be able to access the Item Count within the one-on-one component so that I can apply it to a pagination calculation.

one-on-one.component.html , one-on-one.component.ts , custom filter pipe

Search bar code :

  <input id="tableSearch" type="text" class="form-control" placeholder="Search.." 
  [(ngModel)]="searchText">

table filter :

     <ng-container *cdkVirtualFor="let obj of myArray | searchFilter:  searchText | slice: (page-1) * 
      pageSize : (page-1) * pageSize + pageSize" >

searchFilter comes from the custom filter pipe. searchFilter.pipe.ts Contents :

     import { Pipe, PipeTransform } from '@angular/core';
     import { NGXLogger } from 'ngx-logger';

     @Pipe({
            name: 'searchFilter'
          })
     export class SearchFilterPipe implements PipeTransform {

     constructor(private logger: NGXLogger){}
     /**
     * @param items object from array
     * @param term term's search
     * @param excludes array of strings which will ignored during search
     */
     transform(items: any, term: string, excludes: any = []): any {
      console.log(" the passed in params are :  items = " + items + " term = " + term + " exludes = " + excludes);
      if (!term || !items) return items;
      return SearchFilterPipe.filter(items, term , excludes);
    }

    /**
     *
     * @param items List of items to filter
     * @param term  a string term to compare with every property of the list
     * @param excludes List of keys which will be ignored during search
     */
    static filter(items: Array<{ [key: string]: any }>, term: string, excludes: any): Array<{ [key: string]: any }> {

      const toCompare = term.toLowerCase();

      function checkInside(item: any, term: string) {
        for (let property in item) {
          if (item[property] === null || item[property] == undefined || excludes.includes(property)) {
            continue;
          }
          if (typeof item[property] === 'object') {
            if (checkInside(item[property], term)) {
              return true;
            }
          }
          else if (item[property].toString().toLowerCase().includes(toCompare)) {
            return true;
          }
        }
        return false;
      }

      return items.filter(function (item) {
        return checkInside(item, term);
      });
    }
}

Upvotes: 0

Views: 933

Answers (1)

Ivan Mihaylov
Ivan Mihaylov

Reputation: 433

If I have understood your problem correctly, this should work for you.

parentComponent.ts

    import { Subject } from 'rxjs';

    count = new Subject();

    ngOnInit(){
    this.getEmployees();
    this.count.subscribe(c => console.log('Counting', c));
    console.log("Count " + this.countVar);
  }

parentComponent.html

<tbody>
          <ng-container *ngFor = "let obj of employees | searchFilter:  searchText: count" #countVar>
            <tr>
              <td>{{obj.code}}</td>
              <td>{{obj.name}}</td>
              <td>{{obj.gender}}</td>
              <td>{{obj.salary}}</td>
              <td>{{obj.dob}}</td>
            </tr>
          </ng-container>
         Showing {{count | async}} Employees
        <!-- Showing {{searchResult.length}} Employees -->
</tbody>

pipe.ts

 import { Pipe, PipeTransform, Output, EventEmitter } from '@angular/core';
import { Subject } from 'rxjs';

@Pipe({
  name: 'searchFilter'
})
export class SearchFilterPipe implements PipeTransform {

  constructor(){}
       transform(items: any, term: string, count , excludes: any = []): any {
      if (!term || !items) return items;
      return SearchFilterPipe.filter(items, term , count, excludes);
    }
    static filter(items: Array<{ [key: string]: any }>, term: string, count, excludes: any): Array<{ [key: string]: any }> {

      console.log(term);
      const toCompare = term.toLowerCase();

      function checkInside(item: any, term: string) {
        for (let property in item) {
          if (item[property] === null || item[property] == undefined || excludes.includes(property)) {
            continue;
          }
          if (typeof item[property] === 'object') {
            if (checkInside(item[property], term)) {
              return true;
            }
          }
          else if (item[property].toString().toLowerCase().includes(toCompare)) {
            return true;
          }
        }
        return false;
      }
      const newArr = items.filter(function (item) {
        return checkInside(item, term);
      });

      count.next(newArr.length);
      return newArr;
    }

}

Upvotes: 2

Related Questions