Hi guys,
Today I gonna show you how to define a custom data type in lightning-datatable and how to use it.
What LWC lightning-datatable is?
“A table that displays rows and columns of data.” ~ Salesforce
Is Salesforce solution to display data in a nice table.

We have many predefined types like:
- action
- boolean
- button
- button-icon
- currency
- date
- date-local
- location
- number
- percent
- phone
- text
- URL
but sometimes we will have to create our own type to fulfill the client’s requirements.
Architecture

How to define a custom type?

1. Create a Custom Data Type component
.HTML file contains how table cell will look like. It can be whatever you want. e.g button, picklist, link, etc.
<template>
<button onclick={fireCustomTypeA}>
CustomTypeA - {customValueA}
</button>
</template>
.js file contain typeAttributes and event, which is fire after cell click. Of course, onclick is optional, you can just display data, without custom event sent to parent.
import { LightningElement, api } from 'lwc';
export default class CustomTypeA extends LightningElement {
@api recordId;
@api customValueA;
fireCustomTypeA() {
let newCustomValueA = this.customValueA + 1;
const event = new CustomEvent('customtypea', {
composed: true,
bubbles: true,
cancelable: true,
detail: {
recordId: this.recordId,
newCustomValueA: newCustomValueA
},
});
this.dispatchEvent(event);
}
}
2. Creating a Custom Type Template
.HTML file, which using custom type component created in step number 1. If our component contains some public properties, they can be pass here.
The file should be created in the same place (folder) as the custom lightning datatable described in step 3.
Important!
value is what we used in key-field=”FIELD” in step 4 HTML.
Usually, it is the record Id: key-field=”Id”. This is why in my example I assigned value to record-id.
<template>
<c-custom-type-a
record-id={value}
custom-value-a={typeAttributes.customValueA}
></c-custom-type-a>
</template>
3. Create Custom Lightning Datatable
Out custom datatable, which import templates created in step 2, and configuration for them.
import LightningDatatable from 'lightning/datatable';
import customTypeA from './customTypeA';
import customTypeB from './customTypeB';
export default class CustomLightningDatatable extends LightningDatatable {
static customTypes = {
customTypeA: {
template: customTypeA,
typeAttributes: ['recordId', 'customValueA']
},
customTypeB: {
template: customTypeB,
typeAttributes: ['recordId']
}
}
}
4. Use Custom Lightning Datatable
Use case of the custom data table created in step 3. It contains all standard properties (the same as standard datatable) and our own like custom events.
<template>
<c-custom-lightning-datatable key-field="id"
data={data}
columns={columns}
hide-checkbox-column
oncustomtypea={handleCustomTypeA}
oncustomtypeb={handleCustomTypeB}>
</c-custom-lightning-datatable>
</template>
import { LightningElement, track } from 'lwc';
export default class MyDataTable extends LightningElement {
columns = [
{ label: 'Record Name', fieldName: 'name', type: 'text'},
{ label: 'Custom Type A', fieldName: 'id', type: 'customTypeA', typeAttributes: {
customValueA: { fieldName: 'customA' }
}
},
{ label: 'Custom Type B', fieldName: 'id', type: 'customTypeB', typeAttributes: {
customValueB: { fieldName: 'customB' }
}
}
];
@track data = [
{ id: 1, name: 'Example 1', customA: 1, customB: 11, createdDate: '08-05-2020 '},
{ id: 2, name: 'Example 2', customA: 2, customB: 12, createdDate: '08-05-2020 '},
{ id: 3, name: 'Example 3', customA: 3, customB: 13, createdDate: '08-05-2020 '},
{ id: 4, name: 'Example 4', customA: 4, customB: 14, createdDate: '08-05-2020 '},
{ id: 5, name: 'Example 5', customA: 5, customB: 15, createdDate: '08-05-2020 '},
{ id: 6, name: 'Example 6', customA: 6, customB: 16, createdDate: '08-05-2020 '},
{ id: 7, name: 'Example 7', customA: 7, customB: 17, createdDate: '08-05-2020 '},
{ id: 8, name: 'Example 8', customA: 8, customB: 18, createdDate: '08-05-2020 '}
];
handleCustomTypeA(event) {
const { recordId, newCustomValueA } = event.detail;
console.log('CUSTOM TYPE A - ' + recordId + ' - ' + newCustomValueA);
this.data.find(item => item.id == recordId).customA = newCustomValueA;
this.data = [...this.data];
}
handleCustomTypeB(event) {
const { recordId, customValueB } = event.detail;
console.log('CUSTOM TYPE B - ' + recordId);
}
}
REPOSITORY
You can find generic code, which you can just copy and paste in my repository.
Link: https://github.com/pgajek2/custom-lightning-datatable-type
If you have some questions feel free to ask!
Was it helpful? Check out our other great posts here.
Resource
- https://developer.salesforce.com/docs/component-library/bundle/lightning-datatable/example
- https://developer.salesforce.com/docs/component-library/documentation/lwc/lwc.events_propagation
Hi,
I’ve used this to understand the custom types, it helped me. Thank you.
In regards with point 2. Creating a Custom Type Template
The {value} doesn’t come from the key-field=”FIELD” , it actually comes from the fieldname attribute.
Hi , i’ve added the picklist component in the datatable but it is not saving , any solution
Hi. How to display serial number( row number) as separate column in Custom LWC datatable. Row numbers should display as seperate field. I dont need show-row-number=true.
Hi .. great content..
I have it implemented like this and its working just fine now I have to implement one more column with a dropdown action button (Edit and Delete).
Thanks,
Jai
hi…I need To Implement Opportunity Data table in Lwc ..With out Wire Service ..
Please Suggest Me.
The button event is not reaching my component that contains the custom datatable. It should all be right – the event is “addprogram” and I have “onaddprogram” on the custom datatable, but it’s not firing the method that should be activated.
I have created the custom component for picklist and added in lightning datatable cell column. The component starts displaying in column but it’s not working.
This implementation is uni – direction . you are updating the table data from firing a event from custom types. But how to refresh the custom types values from parent. I tried this.dataRows = […this.dataRows] which usually works for standard columns but no working for custom types. Any ideas please share.