[SalesForce] Get value of lightning-input and lightning-combobox from for loop in LWC

I am displaying data in LWC from an array in a for loop. The loop is using both lightning-input and lightning-combobox for inputs.

<template for:each={tobeOppProduct} for:item="data">
    <div class="slds-grid slds-gutters" key={data.Id}>
        <div class="slds-col slds-text-align_center variant slds-size_1-of-3">
            {data.ProductName}
        </div>
        <div class="slds-col slds-size_1-of-3">
            <lightning-input type="number" name="input1" formatter="currency" step="0.01" value={data.UnitPrice}
                disabled={data.isValue} message-when-bad-input="Please enter a Valid amount"></lightning-input>
        </div>
        <div class="slds-col slds-size_1-of-3">
            <lightning-combobox name="variantValues" placeholder="-Select-" options={data.VariantValueOptions}
                value={data.VariantValue} disabled={data.isNumber}></lightning-combobox>
        </div>
    </div>
</template>

My goal is to get the data changed by the user. the value fields for array tobeOppProduct is not getting updated automatically. Please help me understand how to get the user-selected data from the for loop input fields.

Best Answer

You need to maintain the state of the values in the controller. And to do that, you need to pass in the new values from the loop into the controller via an onchange event, and then update the array in the controller. To identify the record to update, you can set the name of the input to be the data.id, and use event.target.name to then lookup the id in the array Here's a quick example with some sample data. Notice the onchange event to pass in changed value, and the name is set to data.id In the controller, the onchange event read the id, finds in in the tobeOppProduct, and can then update it, or whatever you need to do.

 <template for:each={tobeOppProduct} for:item="data">
        <div class="slds-grid slds-gutters" key={data.Id}>
            <div class="slds-col slds-text-align_center variant slds-size_1-of-3">
                {data.ProductName}
            </div>
            <div class="slds-col slds-size_1-of-3">
                <lightning-input onchange={onfieldchange} type="number" name={data.Id} formatter="currency" step="0.01" value={data.UnitPrice}
                                 message-when-bad-input="Please enter a Valid amount"></lightning-input>
            </div>
            <div class="slds-col slds-size_1-of-3">
                <lightning-combobox onchange={onfieldchange} name={data.Id} placeholder="-Select-" options={VariantValueOptions}
                                    value={data.VariantValue}></lightning-combobox>
            </div>
        </div>
    </template>

Controller:

export default class StackExExample extends LightningElement {

  tobeOppProduct =
    [
      {
        "Id": '1',
        "ProductName": "Prod 1",
        "UnitPrice": 5,
        "VariantValue" : 100
      },
      {
        "Id": '2',
        "ProductName": "Prod 2",
        "UnitPrice": 6,
        "VariantValue" : 102
      }
]

 onfieldchange (event) {
    let dataid = event.target.name;
    let newvalue = event.target.value;

    let currentvalue = this.tobeOppProduct.find(etd => etd.Id == dataid);
    console.log(currentvalue);

  }

  get VariantValueOptions() {
    return [
      {label: '--None--', value: ''},
      {label: 'Option 1', value: 'Option 1'},
      {label: 'Option 2', value: 'Option 2'}
    ];
  } 
 
}