Home > Software design >  Count of filtered ngfor angular
Count of filtered ngfor angular

Time:04-26

Is there an easier way to get the count of actual displayed results in an ngFor that has a nested ngIf without?

<div *ngFor="let stuff of things">
   <ng-container *ngIf="stuff.key === 'value'">
     **I'd like an easier way to get the result of this *ngIf .length and use it elsewhere**
   </ng-container>
</div>

I tried to use @ViewChildren and hoped for;

@ViewChildren('myContainerRef') containerRef: QueryList<any>

<label>Count {{ myContainerRef.length }}</label>
<div #myRef *ngFor="let stuff of things">
</div>

but get undefined result. Is my last resort doing a filter on the incoming array to get the count and assign it public vars? Or is there an easier way to get the count of an ngfor results that match a condition / are displayed?

CodePudding user response:

I would change the logic to allow the filtering to occur in the .ts file and then you have both the iterable and the count...

The following allows the filtering of the original array and the length is the number of matching items

.component.ts
   const filteredThings= things.filter(x => x.key === 'value');

.component.html
   <div *ngFor="let thing of filteredThings">
      {{ thing.xyz }} {{filteredThings.length}}
   </div>

CodePudding user response:

You can use ViewChildren in AfterViewInit at the earliest. You can search for ng-container but would be better to search the elements you're after with #myRef so it would count only the ones you are interested in.

<div *ngFor="let stuff of things">
  <ng-container #myRef>
    {{ stuff }} **I'd like an easier way to get the result of this *ngIf .length
    and use it elsewhere**
  </ng-container>
</div>
<br />
TotalContainers: {{ containersCount }}
@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent implements AfterContentChecked {
  @ViewChildren('myRef') containers: QueryList<ElementRef>;

  things = Array.from(Array(10).keys());
  containersCount: number;

  constructor() {}

  ngAfterContentChecked() {
    this.containersCount = this.containers?.length;
  }
}

Working example: https://stackblitz.com/edit/angular-ivy-vpq5n4?file=src/app/app.component.ts

CodePudding user response:

You can create pipe like this

@Pipe({
  name: 'filterThings',
})
export class FilterThingsPipe implements PipeTransform {

  transform(array: Thing[], value: string): Thing[] {
    return array.filter(item => item.key == value);
  }

}

then use it inside template

<div *ngFor="let stuff of things | filterThings:'val1'; let length = count">
  {{stuff.key}} of {{length}}
</div>
  • Related