0

Custom datatype in LWC datatable, Customizing the Quantity field as a custom input data type and the Price field for inline editing.

When attempting to change the Quantity value, the value is captured, but I also need to capture the row/record ID and the field name. How can this be achieved?"

Also when I change price field both onchange and handleCellChange method is calling.

Below is code snippet

   ├──customInput.html
   ├──CustomTypeGlobal.html
   ├──CustomTypeGlobal.js
   └──CustomTypeGlobal.js-meta.xml

customInput.html

<template>
    <lightning-input name="quantity" type="number" value={typeAttributes.value} onchange={typeAttributes.methodquantity}
        variant="label-hidden" class="slds-input" data-id={rowId}></lightning-input>
</template>

CustomTypeGlobal.html

<template>

</template>

CustomTypeGlobal.js

import LightningDatatable from 'lightning/datatable';
import customInput from './customInput.html'

export default class CustomTypeGlobal extends LightningDatatable {

    static customTypes = {
        quantityInput: {
            template: customInput,
            standardCellLayout: true,
            typeAttributes: ['label', 'value', 'methodquantity'],
        }
    }
}

accountDatatable.js

// accountDatatable.js
import { LightningElement, track } from 'lwc';
import getAccounts from '@salesforce/apex/AccountController.getAccounts';

const columns = [
    { label: 'Account Name', fieldName: 'Name' },
    { label: 'Phone', fieldName: 'Phone' },
    { label: 'Industry', fieldName: 'Industry' },
    {
        label: 'Quantity', hideDefaultActions: true, type: 'quantityInput',
        typeAttributes: {
            value: { fieldName: 'Quantity_one__c' },
            recid: { fieldName: 'Id' },
            methodquantity: { fieldName: 'methodquantity' }
        }
    },
    { label: 'Price', fieldName: 'Price__c', editable: true }
];

export default class AccountDatatable extends LightningElement {
    @track data = [];
    @track error;
    columns = columns;

    connectedCallback() {
        this.fetchAccounts();
    }

    fetchAccounts() {
        getAccounts()
            .then(result => {
                this.data = result;
                this.error = undefined;
                console.log(' this.data -->' + JSON.stringify(this.data));
            })
            .catch(error => {
                this.error = error;
                this.data = undefined;
            });
    }

    handleCellChange(event) {
        console.log('handleCellChange -->' + event.detail);
        
    }

    handleSave() {
        // Collect the draft values from the datatable
        const draftValues = this.template.querySelector('lightning-datatable').draftValues;
        if (draftValues.length > 0) {
        }
    }

    handleChange(event) {
        console.log('Value -->' + event.detail.value);
        console.log('event.detail -->' + JSON.stringify(event.detail));
    }
}

accountDatatable.html

<template>
    <lightning-card title="Account List">
        <!-- <lightning-datatable key-field="Id" data={data} columns={columns} hide-checkbox-column="true"
            oncellchange={handleCellChange} draft-values={draftValues}>
        </lightning-datatable> -->

        <c-custom-type-global key-field="Id" data={data} columns={columns} hide-checkbox-column="true"
            oncellchange={handleCellChange} draft-values={draftValues} onchange={handleChange}>
        </c-custom-type-global>
    </lightning-card>
    <lightning-button label="Save" onclick={handleSave} class="slds-m-top_medium">
    </lightning-button>
</template>

1 Answer 1

1

To get the row/record ID and the field name when changing the quantity value, you need to modify your customInput.html and accountDatatable.js files as follows:

customInput.html

<template>
        <lightning-input name="quantity" type="number" value={typeAttributes.value} onchange={handleQuantityChange} variant="label-hidden" class="slds-input" data-id={typeAttributes.recid} data-field="Quantity_one__c">
        </lightning-input>
</template>

accountDatatable.js

Update the handleChange method to capture the row ID and field name:

handleChange(event) {
        const rowId = event.target.dataset.id;
        const fieldName = event.target.dataset.field;
        const value = event.detail.value;

        console.log('Row ID:', rowId);
        console.log('Field Name:', fieldName);
        console.log('Value:', value);
}

Update:

I have tried it on my org and the below code is working as expected. I have referred to this document: https://developer.salesforce.com/docs/platform/lwc/guide/data-table-custom-types-events.html

First, I have created one component for the input.

CustomInput
   ├──CustomInput.html
   ├──CustomInput.js
   └──CustomInput.js-meta.xml

CustomInput.html

<template>
    <lightning-input type={inputType} value={value} label={label} variant="label-hidden" class="slds-input"
        onchange={handleChange}>
    </lightning-input>
</template>

CustomInput.js

import { LightningElement, api } from 'lwc';

export default class CustomInput extends LightningElement {

    @api inputType;
    @api value;
    @api label;
    @api recordId;
    @api fieldName;

    handleChange(event) {
    const newValue = event.target.value;

    const inputChange = new CustomEvent('inputchange', {
        composed: true,
        bubbles: true,
        cancelable: true,
        detail: {
            value: newValue,
            recordId: this.recordId,
            fieldName: this.fieldName,
        },
    });
    this.dispatchEvent(inputChange);
    }
}

CustomInput.js-meta.xml

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>61.0</apiVersion>
    <isExposed>true</isExposed>
</LightningComponentBundle>

After that, I created the custom-type component.

CustomTypeGlobal
   ├──customInputs.html
   ├──CustomTypeGlobal.js
   └──CustomTypeGlobal.js-meta.xml

customInputs.html

<template>
    <c-custom-input input-type={typeAttributes.inputType} value={typeAttributes.value} label={typeAttributes.label}
        record-id={typeAttributes.recordId} field-name={typeAttributes.fieldName}>
    </c-custom-input>
</template>

CustomTypeGlobal.js

import LightningDatatable from 'lightning/datatable';
import customInputs from './customInputs.html'

export default class CustomTypeGlobal extends LightningDatatable {

    static customTypes = {
        customInput: {
            template: customInputs,
            standardCellLayout: true,
            typeAttributes: ['inputType', 'value', 'label', 'recordId', 'fieldName'],
        },
    };
}

CustomTypeGlobal.js-meta.xml

<?xml version="1.0"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>60.0</apiVersion>
    <isExposed>true</isExposed>
</LightningComponentBundle>

After that, I created the custom data table component.

CustomDataTypeTest
   ├──CustomDataTypeTest.html
   ├──CustomDataTypeTest.js
   └──CustomDataTypeTest.js-meta.xml

CustomDataTypeTest.html

<template>
    <!--Test NEW-->
    <lightning-card title="Account List">   
        <c-custom-type-global key-field="Id" data={new_data} columns={new_columns} hide-checkbox-column="true"
            oncellchange={handleCellChange} draft-values={draftValues} oninputchange={handleChange} >
        </c-custom-type-global>
    </lightning-card>
    <lightning-button label="Save" onclick={handleSave} class="slds-m-top_medium">
    </lightning-button>
    <!--End-->
</template>

CustomDataTypeTest.js

import { LightningElement, track } from 'lwc';
import getAccounts from '@salesforce/apex/AccountController.getAccounts';
const test_columns = [
    { label: 'Account Name', fieldName: 'Name' },
    { label: 'Phone', fieldName: 'Phone' },
    { label: 'Industry', fieldName: 'Industry' },
    {
        label: 'Quantity', 
        hideDefaultActions: true, 
        type: 'customInput',
        typeAttributes: {
            inputType: 'number',
            value: { fieldName: 't561258__Test_Number__c' },
            label: 'Quantity',
            recordId: { fieldName: 'Id' },
            fieldName: 't561258__Test_Number__c',
        },
    },
    {
        label: 'Email', 
        hideDefaultActions: true, 
        type: 'customInput',
        typeAttributes: {
            inputType: 'email',
            value: { fieldName: 't561258__Email__c' },
            label: 'Email',
            recordId: { fieldName: 'Id' },
            fieldName: 't561258__Email__c',
        },
    },
    {
        label: 'Phone', 
        hideDefaultActions: true, 
        type: 'customInput',
        typeAttributes: {
            inputType: 'phone',
            value: { fieldName: 'Phone' },
            label: 'Phone',
            recordId: { fieldName: 'Id' },
            fieldName: 'Phone',
        },
    },
    { label: 'Price', fieldName: 'AnnualRevenue', editable: true },
];


export default class CustomDataTypeTest extends LightningElement {
    //test
    @track new_data = [];
    @track new_error;
    new_columns = test_columns;
    connectedCallback() {
        this.fetchAccounts();
    }

    fetchAccounts() {
        getAccounts()
            .then(result => {
                this.new_data = result;
                this.new_error = undefined;
                console.log(' this.data -->' + JSON.stringify(this.new_data));
            })
            .catch(error => {
                this.new_error = error;
                this.new_data = undefined;
            });
    }

    handleCellChange(event) {
        console.log('New Test handleCellChange -->' + event.detail);       
    }

    handleSave() {
        // Collect the draft values from the datatable
        const draftValues = this.template.querySelector('lightning-datatable').draftValues;
        if (draftValues.length > 0) {
        }
    }

    handleChange(event) {
        const { recordId, value, fieldName } = event.detail;
        console.log('details:: '+ JSON.stringify(event.detail));
        console.log('const recordId:', recordId);
        console.log('const value:', value);
        console.log('const fieldName:', fieldName);
    }

}

CustomDataTypeTest.js-meta.xml

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>61.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__RecordPage</target>
        <target>lightning__AppPage</target>
        <target>lightning__HomePage</target>
        <target>lightning__Tab</target>
    </targets>
</LightningComponentBundle>

Apex Class:

public class AccountController {    
    @AuraEnabled
    public static List<Account> getAccounts() {
        return [SELECT Id, Name, t561258__Email__c, Phone, Industry, t561258__Test_Number__c, AnnualRevenue FROM Account LIMIT 2000];
    }
}

Output:: enter image description here

Note: I have used my org field in this example. You need to change the field name as per your org.

7
  • Getting undefined on rowid and fieldName Commented Aug 5 at 6:16
  • @SK2889, In the accountDatatable.js, make sure that you have given the type as your custom type name in column. ex. { label: 'Quantity', hideDefaultActions: true, type: 'customInput', typeAttributes: { value: { fieldName: 'Quantity_one__c' }, recid: { fieldName: 'Id' }, methodquantity: { fieldName: 'methodquantity' } } } Commented Aug 5 at 6:34
  • You can refer to this: developer.salesforce.com/docs/platform/lwc/guide/… Here given the example. Commented Aug 5 at 6:36
  • Yes i have given custom type name as "type: 'quantityInput'" Commented Aug 5 at 7:08
  • @SK2889, I have tried your code in my org and based on that I have made some changes to the code. see the update section of my answer. Commented Aug 5 at 11:23

You must log in to answer this question.

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