MotoRidingMelon
MotoRidingMelon

Reputation: 2547

How can one count iterations of Angular 9 ngFor without using index or .length?

I have an Angular loop that has a conditional check in it. Thus, the usual answer of using the .length on the array, or using the i from index won't tell me how many items are showing.

<form [formGroup]="paymentsForm">
<div formArrayName="arrVoucherLines">  
    <div *ngFor="let line of paymentsForm.get('arrVoucherLines')['controls']; index as i"
     [formGroupName]="i">

     <div *ngIf="dateCheckingConditionalFunctionPlaceholder()">

         <mat-checkbox formControlName='FlagPayInvoice'></mat-checkbox>
         Issued: {{line.value.DateTimeLocalInvoiceIssued |date:'MM/dd'}}
         Due: {{line.value.DateTimeLocalInvoiceDue |date:'MM/dd'}}
        ... variety of other voucer info
    </div>
    </div>
</div>
</form>

Displaying the total amount of items is easy, but I want to also be able to display how many are shown and how many were skipped. If I could have a "variable++" in the loop that would be pretty easy.

Desired result would be to end up with something that I could:

Total invoices {{blah.length}}
Invoices Shown {{count}}
Invoices not yet due: {{blah.length-count}}

The usage case is the user is selecting a cutoff date on the form, and only showing the bills due before that date.

Upvotes: 4

Views: 3957

Answers (1)

Quentin Grisel
Quentin Grisel

Reputation: 4987

You could write a simple directive that do the job. Check this repro on stackblitz. It counts only 2 divs out of 12 because the directive is triggered only if the div is created. Here is the code just in case stackblitz does not works:

app.ts:

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

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  array = new Array(12);
  counter = 0;

  addCounter(e:number) {
    this.counter += 1;
  } 
}

app.html:

<div *ngFor="let item of array; let i = index">
    <div *ngIf="i === 3 || i ===4" ngInit (trigger)="addCounter()">
        item {{i}}
    </div>
</div>
<hr>
<div>Total items = {{array.length}}</div>
<div>Generated items = {{counter}}</div>
<div>Skipped items = {{array.length - counter}}</div>

ng-init.directive.ts:

import {Directive, Input, Output, EventEmitter} from '@angular/core';

@Directive({
  selector: '[ngInit]'
})
export class NgInitDirective {
  @Output() trigger: EventEmitter<any> = new EventEmitter();

  ngOnInit() {
    this.trigger.emit();
  }
}

In the html file I used the index to add a condition on the displayed div, you have a condition based on something else but it does not change anything. For the number of items skipped, well array.length - this.counter will do the job.

Upvotes: 7

Related Questions