0

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);
      });
    }
}
6
  • You can pass to your pipe an eventEmmiter as a third parameter that is declared in your component that will return the count of the items as an observable to which you can subscribe and react when the pipe triggers. Commented Jan 22, 2020 at 16:02
  • Please make an example here: stackblitz.com Commented Jan 22, 2020 at 16:20
  • @IvanMihaylov Can you show me a mock example or a link to how that works please Thanks ! Commented Jan 22, 2020 at 17:00
  • I am not going to write a stackblitz for you @Steve020 . If you provide one, maybe I can look at it. Alternatively you can check out this approach. stackoverflow.com/questions/59421884/… Commented Jan 23, 2020 at 8:01
  • stackblitz.com/edit/fakeinc-qctyhf @IvanMihaylov Commented Jan 23, 2020 at 18:49

1 Answer 1

2

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

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

Comments

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.