0

I have a simple custom pipe in Angular2 to filter an array based on type ID and year arrays, I define it as such:

@Pipe({name: 'highlightedWorksFilter', pure: false})
export class HighlightedWorksFilterPipe implements PipeTransform {
transform(works: IHighlightedWork[], activityTypeIds: any[], activityYears: any[]){
    if (works && works.length) {
        return works.filter(work => {
            if(activityTypeIds.findIndex(i => i.id === work.activityTypeId && i.checked) === -1) {
                return false;
            }
            if (activityYears.findIndex(i => i.year === work.activityYear && i.checked) === -1) {
                return false;
            }
            return true;
        });
    }
    else {
        return works;
    }
}
}

Here's where it's used from a calling component:

<div>FILTERED COUNT / {{highlightedWorks.length}}</div>
<div *ngFor="let work of highlightedWorks | highlightedWorksFilter: myActivityTypeIds:myActivityYears">
 {{work.Title}}
</div>

The filter works perfectly and gets updated based on the 2 checkbox list arrays for type and year (using arrays to filter, hence the the "pure: false" on the pipe).

My question is, how can I get that FILTERED COUNT outside of the ngFor to display the pipe's filtered results count? I have the highlightedWorks.length as the total results count, but want to also display how many results I currently have filtered with the pipes.

Mike Feltman
  • 5,160
  • 1
  • 17
  • 38
Andy
  • 1,243
  • 3
  • 22
  • 40
  • I hope this answer your question https://stackoverflow.com/questions/35127257/how-to-get-the-size-of-a-filtered-piped-set-in-angular2 – CharanRoot Jul 06 '17 at 18:57
  • @Jonnysai I have tried this approach, but {{filteredItems?.length}} only seem to update to the next value after an another change is made. It appears to be one step behind. – Andy Jul 06 '17 at 19:07
  • Possible duplicate of [How to find the count of items in an ngFor after the pipes have been applied](https://stackoverflow.com/questions/36073671/how-to-find-the-count-of-items-in-an-ngfor-after-the-pipes-have-been-applied) – Roman C Jul 06 '17 at 19:52

2 Answers2

0

I'd suggest performing the filtering in the component code instead of in a pipe for the reasons stated here: https://angular.io/guide/pipes#appendix-no-filterpipe-or-orderbypipe

Then you'd have access to the filtered list as a property of the component class so can more easily get its length.

Here is an example

import { Component, OnInit } from '@angular/core';

import { IProduct } from './product';
import { ProductService } from './product.service';

@Component({
    templateUrl: './product-list.component.html'
})
export class ProductListComponent implements OnInit {

    _listFilter: string;
    get listFilter(): string {
        return this._listFilter;
    }
    set listFilter(value: string) {
        this._listFilter = value;
        this.filteredProducts = this.listFilter ? this.performFilter(this.listFilter) : this.products;
    }

    filteredProducts: IProduct[];
    products: IProduct[] = [];

    constructor(private _productService: ProductService) {

    }

    performFilter(filterBy: string): IProduct[] {
        filterBy = filterBy.toLocaleLowerCase();
        return this.products.filter((product: IProduct) =>
              product.productName.toLocaleLowerCase().indexOf(filterBy) !== -1);
    }

    ngOnInit(): void {
        this._productService.getProducts()
                .subscribe(products => {
                    this.products = products;
                    this.filteredProducts = this.products;
                },
                    error => this.errorMessage = <any>error);
    }
}
DeborahK
  • 57,520
  • 12
  • 104
  • 129
0

You can use a simple index on *ngFor which last value is the index of last filtered element. You add 1 to that value and you have the length of your filtered list.

<div *ngFor="let work of highlightedWorks | highlightedWorksFilter: myActivityTypeIds:myActivityYears; let i=index" [i]="i">
 {{work.Title}} Index: {{i+1}}
</div>

You also have to input the value into your component for this to work:

@Input() i: number;
BogdanC
  • 2,746
  • 2
  • 24
  • 22
  • Thanks, but I'm looking to show the count outside of the element with the ngFor on it. It doesn't look like this would work for it? – Andy Jul 08 '17 at 03:06
  • If you want to show it outside of the ngFor, you have to pass the info from the child to the parent. You can do that by raising an event on the child that you will pass to the parent with the @output decorator. If you want to implement this, you can find it explained [here](https://www.themarketingtechnologist.co/building-nested-components-in-angular-2/) – BogdanC Jul 10 '17 at 16:19