eivanovue
eivanovue

Reputation: 23

Angular *ngFor variable scope for event handler

I have just started learning Angular and found out that the ngFor is placed on the child element that should repeat instead of the parent element (e.g. a list of elements that repeat).

<select  class="form-control" id="sel {{order.product.id}}">
  <option (click)="this.unsetProductSize(order)" selected>Select size...</option>
  <option (click)="this.setProductSize(order, size.id, size.size, size.stock)" *ngFor="let size of order.product.productSize">{{size.size}}</option>
</select>

So the issue here is that the "click" event handler will only work on Firefox. It is not the right way to do this as the handler should be on the select element (parent) and must be a "change" event handler.

The variable scope from the ngFor ("size") will be outside of scope if I move the functions to the select element. I need each function to be executed for each product as I will have multiple select elements. My question is, is there a known way to solve this, or maybe a for each that is placed on the parent element instead of the child?

Upvotes: 1

Views: 765

Answers (3)

AVJT82
AVJT82

Reputation: 73377

This is the perfect use for [(ngModel)]. Also use [ngValue] to capture the whole object chosen. Also you don't need the function unsetProductSize, since you can use setProductSize to check if value exists or not. Also, don't use this in template. So all in all, I suggest the following:

<select [(ngModel)]="selectedSize" (ngModelChange)="setProductSize(order)">
  <option [ngValue]="null">Select size...</option>
  <option [ngValue]="size" *ngFor="let size of order.product.productSize">
    {{size.size}}
  </option>
</select>

TS:

selectedSize = null;

setProductSize(order) {
  console.log(order) // order here
  if (this.selectedSize) {
    // do stuff
  } else {
    // do other stuff!
  }
}

STACKBLITZ

Upvotes: 0

Shashikant
Shashikant

Reputation: 103

You can and the click event on the select box. please refer following code

<select  class="form-control" (click)="setProductSize(order, $event.target.value)"  id="sel {{order.product.id}}">
  <option selected value="0">Select size...</option>
  <option  *ngFor="let size of order.product.productSize" [value]="size">{{size.size}}</option>
</select>

In the .ts file, you can write your functionality

setProductSize(order, size){
//You have whole order object in order variable and selected size object in size variable
//if user click on Select size... option in size variable you will get the value 0. you can add condition according to the selected values
}

Thank you.

Upvotes: 0

Andrei
Andrei

Reputation: 12206

try this

<select  class="form-control" id="sel {{order.product.id}}" (change)="handleProductSizeChange($event)">
  <option [value]="null" selected>Select size...</option>
  <option [value]="size" *ngFor="let size of order.product.productSize">{{size.size}}</option>
</select>

every option has a value and a single handler for option changes is used at a select element

Upvotes: 1

Related Questions