0

In one of my requirements I am having a empty table with just one blank row having some 5 columns. I can enter new record/data on the rows. On one particular column, when the user enters the data on it, the entered data needs to be populated on another column in all the other rows.

How can I achieve this, below code I am trying out: Please will be thankful for any assistance. I have been stuck on this. enter image description here


JS CODE : 

//Below handler (updateValues) called upon entering value on the column whose entered value should be populated on another column of all other rows
//Here , 'Approved' is an column, so what ever value I enter here, its value should be instantly populated on the 'Approved' column of all other rows 
updateValues(event){
var foundelement = this.records.find(ele => ele.Id ==  event.target.dataset.id);
else if(event.target.name === 'Approved')
{
    foundelement.Approved_Percent__c = event.target.value;

    this.records.forEach(res =>{                       
        res.Approved_Percent__c = event.target.value;
          });    
}




//On component launch from Quick action button - To add one dummy row
constructor()  
{
let randomId = Math.random() * 16;
super();
// Enter Single empty row on component load
this.records = [{Case__c:this.recordId,Part_Number__c: "", Part_Name__c: "", Id:randomId, Quantity__c: "",MPS_Source__c:"",Unit_Price__c:"",Number_Parts_Requested__c:"",Number_Parts_Sent__c:"",Approved_Percent__c:"",Total_Approved_Price__c:0}];
}


//On click of Add button, add a new row
addRow() {
    //To add new row on press of 'Add Row' button
let randomId = Math.random() * 16;
let myNewElement  = {Case__c:this.recordId,Part_Number__c: "" , Part_Name__c: "", Id:randomId, Quantity__c: "",MPS_Source__c:"",Unit_Price__c:"",Number_Parts_Requested__c:"",Number_Parts_Sent__c:"",Approved_Percent__c:"",Total_Approved_Price__c:0};
this.records = [...this.records, myNewElement];
}

--HTML CODE:

<template for:each={records} for:item="obj">
<td data-label="Approved %">                                   
<lightning-input type="text" class="fields" variant="label-hidden" label="Approved %" name="Approved" value={obj.Approved} data-id={obj.Id} onchange={updateValues}></lightning-input>
</td>
</template>

Updated on 02-October-2022


Thank you much for the detailed code. I am trying to achieve the same. However, I am stuck on below code where I dont get the hold of the HTML element using queryselector:

//JS CODE Fired on Value Change on the HTML Table Column

updateValues(event){
var foundelement = this.records.find(ele => ele.Id ==  event.target.dataset.id);

if(event.target.name === 'Approved')
{
    foundelement.Approved_Percent__c = event.target.value;

//Looping through all other table rows , and populating the 'Approved' column value to the value entered on the current row
    this.records.forEach(res =>{
const input = this.template.querySelector(`lightning-input[name="Approved"][data-id="${res.Id}"]`);
// input always comes as blank //
    if(input) {
      input.value =  event.target.value;
    }

    });
    }  

//HTML CODE:

<th class="" scope="col">                                    
<div class="slds-truncate" title="Approved %">Approved %</div>
</th>

<template for:each={records} for:item="obj">
<tr class="inputRows" key={obj.Id}>
<td data-label="Approved %">                                        
<lightning-input type="text" class="fields" variant="label-hidden" label="Approved %" name="Approved" value={obj.Approved} data-id={obj.Id} onchange={updateValues}></lightning-input>                                         
</td>
</template>
6
  • You probably need to reassign the records property so the lwc rerenders, such as this.records = [...this.records]; Commented Sep 30, 2022 at 15:59
  • I actually tried this, but does not render Commented Sep 30, 2022 at 16:05
  • are you using lightning-datatable? and is the records property linked to data in the datatable? Commented Sep 30, 2022 at 16:35
  • No not lightning datable Just html code table. However u tried via lightning data table that also dud not work Commented Sep 30, 2022 at 16:37
  • then you probably need to use querySelector to get all the inputs you want to fill, and set the value property of those inputs. Commented Sep 30, 2022 at 16:39

1 Answer 1

0

I wrote a simple example of how one might accomplish this. Basically, you just need to set the desired values. As an HTML table, you have to set the values yourself, while with lightning-datatable, you'd set the values in the data in order to affect the changes. The demo includes both a basic HTML table without any styling, and a lightning-datatable.


import { LightningElement } from "lwc";

const input = true;
const readonly = true;
const editable = true;

export default class App extends LightningElement {
  // A combination of attributes to use both table and lightning-datatable
  columns = [
    { 
      id: 0, 
      name: 'Input 1', 
      fieldName: 'Input 1', 
      label:'Input 1', 
      type: 'number', 
      editable, 
      input 
    },
    { 
      id: 1,
      action: (event) => this.deleteRow(event), 
      label: 'Action', 
      type: 'button-icon',
      buttonLabel: 'Delete', 
      typeAttributes: { 
        type:'button-icon', 
        name: 'delete',
        value: 'delete',
        label: 'Delete',
        iconName:'utility:delete',
        disabled: false,
      }
    },
  ]
  rows = [
    { id: 0 }
  ]
  handleRowDelete(event) {
    this.rows.splice(event.detail.id, 1);
    this.renumberRows();
  }
  handleCellChange(event) {
    const { draftValues } = event.detail;
    // The first row comes across as row-0, while the others are just numbers
    const rowId = draftValues[0].id === 'row-0'? 0: parseInt(draftValues[0].id);
    this.rows[rowId]['Input 1'] = draftValues[0]['Input 1'];
    this.renumberRows();
  }
  deleteRow(event) {
    this.rows.splice(event.target.dataset.row, 1);
    this.renumberRows();
  }
  // async is a required keyword to use await
  async renumberRows() {
    // lightning-datatable doesn't like it when you take away the last row, so ensure at least one
    if(!this.rows.length) {
      this.rows.push({});
    }
    // This waits for one render cycle, so we can later update the input fields
    await Promise.resolve();
    // Reset the edited state
    this.template.querySelector('lightning-datatable').draftValues = [];
    // Calculate new values for Input 2
    this.rows = this.rows.map((row, id) => ({...row, id }));
    // Fill the inputs with their new values, lightning-datatable does this automatically
    this.rows.forEach((row)=>{
      this.columns.filter(
        (column)=>column.input
      ).forEach((column)=>{
        const input = this.template.querySelector(`input[name="${column.name}"][data-row="${row.id}"]`);
        if(input) {
          input.value = row[column.name];
        }
      })
    });
  }
  // This is the HTML table value change
  handleValueChange(event) {
    const { dataset, name, value } = event.target;
    if(name === 'Input 1') {
      this.rows.forEach((row)=> { row[name]=value; });
    } else {
      this.rows[dataset.row][name] = value;
    }
    this.renumberRows();
  }
  // Handles both tables at once
  handleAddRow(event) {
    this.rows.push({});
    this.renumberRows();
  }

}

<template>
    <lightning-layout>
        <lightning-layout-item size="6">
            <table onchange={handleValueChange}>
                <thead>
                    <tr>
                        <th for:each={columns} for:item="column" key={column.id}>
                            {column.label}
                        </th>
                    </tr>
                </thead>
                <tbody>
                    <tr for:each={rows} for:item="row" key={row.id}>
                        <td width="50%" for:each={columns} for:item="column" key={column.id}>
                            <input if:true={column.input} data-row={row.id} name={column.name} type={column.type} readonly={column.readonly}/>
                            <button if:true={column.action} onclick={column.action}>{column.buttonLabel}</button>
                        </td>
                    </tr>
                </tbody>
                <tfoot>
                    <tr>
                        <td>
                            <button onclick={handleAddRow}>Add</button>
                        </td>
                    </tr>
                </tfoot>
            </table>
        </lightning-layout-item>
        <lightning-layout-item size="6">
            <lightning-datatable data={rows} columns={columns} oncellchange={handleCellChange} key-field="id"
                suppress-bottom-bar onrowaction={handleRowDelete}>
            </lightning-datatable>
            <button onclick={handleAddRow}>Add</button>
        </lightning-layout-item>
    </lightning-layout>
</template>

Demo.

3
  • Thank you much for the detailed code. I am trying to achieve the same. However, I am stuck on below code where I dont get the hold of the HTML element using queryselector: Commented Oct 2, 2022 at 7:35
  • Please could you check the description on top on my post to see the revised code I am trying out wherein queryselector returning null Commented Oct 2, 2022 at 7:46
  • Please can anyone give their inputs Commented Oct 4, 2022 at 6:23

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .