Pass ngFor index to click event?

Here’s the scenario, i need to pass the index of the element to a click event rather that the item itself, but the next code gives error when i just basically took it from the Angular 2 docs:

< ion-item *ngFor="#prod of products; #i = index" (click)=“editProduct(i)”>

and error:

EXCEPTION: Error during evaluation of “click”
(index):29 EXCEPTION: Error during evaluation of "click"console.(anonymous function) @ (index):29BrowserDomAdapter.logError @ app.bundle.js:37269BrowserDomAdapter.logGroup @ app.bundle.js:37279ExceptionHandler.call @ app.bundle.js:10953(anonymous function) @ app.bundle.js:20193NgZone._notifyOnError @ app.bundle.js:20829errorHandling.onError @ app.bundle.js:20727run @ app.bundle.js:5141(anonymous function) @ app.bundle.js:20742NgZone.run @ app.bundle.js:20691outsideHandler @ app.bundle.js:35609run @ app.bundle.js:5138zoneBoundFn @ app.bundle.js:5111
(index):29 ORIGINAL EXCEPTION: ReferenceError: i is not defined

Note that last line says ReferenceError: i is not defined which means that i doesn’t exist for the (click) event, but inside i have an interpolation that shows the index and it is correct, how do i pass the index to the (click) event?

My fail, was in the controller, nothing to do with the ngFor :relaxed:

I know it’s a bit late for this question but for anybody else who’s looking for an answer.

< ion-item *ngFor="prod of products; let i = index" (click)="editProduct(i)">
4 Likes

Yeah, a bit late, also i think in latest version it needs a let before prod in the start of the ngFor.

Hello guys! please i need help with this, this code increment a count on click, work perfectly, i want to make the increment unique to the button click instead increment all button in the ngFor list. can someone help to show how to get index or something.

//.ts files
// increment product qty
incrementQty(count, i) {
count = this.count[i] += 1;
}

// decrement product qty
decrementQty(count, i) {

if(this.count[i]-1 < 1 ){
  count= this.count[i] = 1
  console.log('1->'+count);
}else{
  count =this.count[i] -= 1;
  console.log('2->'+count);
}

}

//template
    <ion-list *ngFor="let list of products" let i = index>
  <ion-item>
    <ion-avatar item-left>
      <img src="http://placehold.it/50x50">
    </ion-avatar>
    <h2>{{list.name}}</h2>
    <p>{{list.price}}/Piece</p>
    <span item-right >
      <button clear  (click)="incrementQty(count, i);"  [value] ="count"><ion-icon name="add-circle" ></ion-icon></button> {{count[i]}} 
      <button clear (click)="decrementQty(count, i)" [value] ="count"><ion-icon name="remove-circle" ></ion-icon></button></span>
  </ion-item>
</ion-list>

I would restructure this to add a count property to each element in the products array instead of having a separate shadow array. That way you don’t have to care about indexes and the code should be cleaner and easier to understand. You can also disable the decrement button when the count goes to 1, which eliminates the need for two code paths in the decrement case.

@rapropos, please can you just show me in code, cos the count is independent of the ngFor.

I’m suggesting making it dependent.

<ion-list>
<ion-item *ngFor="let prod of products">
<span item-right>{{prod.qty}}
<button (click)="inc(prod)">+</button>
<button (click)="dec(prod)" [disabled]="prod.qty <= 1">-</button>
</span>
</ion-item>
</ion-list>
inc(prod: Product): void [
  prod.qty = prod.qty + 1;
}

dec(prod: Product): void {
  prod.qty = prod.qty - 1;
}
1 Like

@rapropos, thanks, but i wanted to allow the product selector to add or remove product qty which will be different from the set price per product by the product vendor which originally set to 1 by default. so what i wanted is for product to have initial of zero when viewed by the customer and then allow him to add as many item as possible and collect sum on checkout.

however, your approach did give me an insight on how i can implement that by setting the prod.qty = 0 by default for the customer, cos the data is saved to a different collection with customer Id.

Thank you!