I'm using a CustomDataTable by extending LightningDataTable for custom DataType in lightning data table. I've used Picklist and lookup data type as custom data type in the lightning Data Table. Please see the below screenshot.
The problem is the the alignment of the column header. The columns seems to be overlapping. I've also attached another screenshot below where it is more evident.
On the code front I've used custom css from Static resource for the custom datatype in the datatable- i.e for picklist and for the lookup in the inline editing.
Main Component - CustomDataTableDemo.html
<template>
<div class="slds-media__body">
<h2 class="slds-card__header-title">
<span>{lblobjectName} ({recordCount})</span>
</h2>
</div>
<div class="slds-table slds-table_cell-buffer slds-table_bordered slds-table_col-bordered
slds-table_bordered slds-table_fixed-layout slds-table_resizable-cols">
<template if:true={data}>
<c-custom-data-table
key-field="Id"
data={tableData}
columns={columns}
onpicklistchanged={picklistChanged}
onvalueselect={handleSelection}
draft-values={draftValues}
oncellchange={handleCellChange}
onsave={handleSave}
oncancel={handleCancel}
hide-checkbox-column>
</c-custom-data-table>
</template>
</div>
</template>
CustomDatableDemo.js-
connectedCallback(){
let firstTimeEntry = false;
let firstFieldAPI;
//make an implicit call to fetch records from database
getInlineEditingWrapper({ strObjectApiName: this.SFDCobjectApiName,
strfieldSetName: this.fieldSetName,
criteriaField: this.criteriaFieldAPIName,
criteriaFieldValue: this.recordId,
componentLabel: this.componentLabel,
strUnEditableFields: this.unEditableFields,
strSortableFields: this.sortableFields})
.then(data=>{
this.data = data;
let listOfFields= data.lstCoulmns;
this.lblobjectName = data.objectLabel;
this.tableData = data.lstRecords;
this.columns = data.lstCoulmns;
this.refreshResult = data.lstRecords;
this.lastSavedData = data.lstRecords;
//console.log('Stringify::',JSON.stringify(data));
console.log('Stringify::this.columns',JSON.parse(JSON.stringify(this.columns)));
console.log('Stringify::this.tableData',JSON.stringify(this.tableData));
//retrieve listOfRecords from the map
let listOfRecords = data.lstRecords;
this.recordList = listOfRecords;
let items = [];
listOfFields.map(element=>{
//it will enter this if-block just once
if(this.firstColumnAsRecordHyperLink !=null && this.firstColumnAsRecordHyperLink=='Yes'
&& firstTimeEntry==false){
firstFieldAPI = element.fieldApiName;
//perpare first column as hyperlink
items = [{
label: element.label,
fieldName: 'URLField',
fixedWidth: 150,
type: 'url',
typeAttributes: {
label: {
fieldName: element.fieldName
},
target: '_blank'
},
sortable: true ,
editable: false
}];
firstTimeEntry = true;
}else{
items = [...items ,{
label : element.label,
fieldName : element.fieldName,
type: element.type,
fixedWidth: 150,
editable : element.editable,
minColumnWidth: 150,
typeAttributes : element.typeAttributes,
}];
}
});
//finally assigns item array to columns
this.columns = items;
//if user wants to display first column has hyperlink and clicking on the link it will
// naviagte to record detail page. Below code prepare the field value of first column
if(this.firstColumnAsRecordHyperLink !=null && this.firstColumnAsRecordHyperLink=='Yes'){
let URLField;
//retrieve Id, create URL with Id and push it into the array
this.tableData = listOfRecords.map(item=>{
URLField = '/lightning/r/' + this.SFDCobjectApiName + '/' + item.Id + '/view';
return {...item,URLField};
});
//now create final array excluding firstFieldAPI
//this.tableData = this.tableData.filter(item => item.fieldPath != firstFieldAPI);
}
this.recordCount = this.tableData.length;
this.error = undefined;
})
.catch(error =>{
this.error = error;
console.log('error',error);
this.tableData = undefined;
this.lblobjectName = this.SFDCobjectApiName;
}) f//refreshApex(this.data);
}
CustomDataTable- Component where the custom data types are wired up and this extends LightningDataTable
import {api,wire} from 'lwc';
import LightningDatatable from 'lightning/datatable';
//import the template so that it can be reused
import DatatablePicklistTemplate from './picklist-template.html';
import DependentDatatablePicklistTemplate from './dependent-picklist-template.html';
import lookupTemplate from './lookup-template.html';
import {
loadStyle
} from 'lightning/platformResourceLoader';
import CustomDataTableResource from '@salesforce/resourceUrl/CustomDataTable';
export default class CustomDataTable extends LightningDatatable {
static customTypes = {
picklist: {
template: DatatablePicklistTemplate,
standardCellLayout: true,
wrapText: true,
typeAttributes: ['label', 'placeHolder', 'listPicklistEntry', 'pickListApiName', 'pickListContext','isControllingPicklist'],
},dependentpicklist: {
template: DependentDatatablePicklistTemplate,
wrapText: true,
standardCellLayout: true,
typeAttributes: ['label', 'placeHolder','pickListDependency','pickListApiName', 'pickListContext','parentselectedvalue','controllingvalue'],
},
lookup: {
template: lookupTemplate,
standardCellLayout: true,
wrapText: true,
typeAttributes: ['pickListContext','lookUpValueId', 'lookUpObjectName', 'icon', 'label', 'displayFields', 'displayFormat', 'placeholder', 'filters','lookupReadOnly']
}
};
constructor() {
super();
Promise.all([
loadStyle(this, CustomDataTableResource),
]).then(() => {})
}
renderedCallback(){
}
}
I've added Picklist, Dependent Picklist and Lookup field as the custom Data Types by creating different component for these data types. I'll share the code for them if needed.
The CSS that I'm using is loaded from static resource but is only created for formatting of custom data types component and for adding fix length to first column of the header. The CSS is provided below-
CustomDataTable.css
.picklist-container,
.lookup-container{
width : 90%;
margin: 0 auto;
}
.picklist-container .slds-dropdown,
.lookup-container .slds-dropdown{
position: relative !important;
z-index: 99 !important;
max-height: 120px;
overflow: scroll;
}
[lightning-combobox_combobox-host]{
margin-bottom: 17px;
}
th.slds-has-focus, td.slds-has-focus{
box-shadow: none !important;
}
.slds-table_bordered col .slds-table_col-bordered,
.slds-table_edit thead th:first-child{
width: 60px;
}
.slds-table_bordered col .slds-table_col-bordered,
.slds-table_edit thead th:not(:first-child){
width: fit-content;
}
picklist-container,lookup-container are classes used to div the custom components for respective data types.
I've also tried using different attributes from table class like adding border to the table and columns but that adds border between the rows and not the header columns. I've also tried using truncate on the column but that didn't work either.
Any suggestion are welcomed since front end and css are something that I'm still learning.
Also sharing the sample columns and rows that are populating the data in this datatable-
Below is Table Data i.e this.columns and this rows/tableData
this.columns = Stringify::this.columns [{"editable":false,"fieldName":"Product2Id","isDatabaseRequired":false,"label":"Sanofi Product","sortable":false,"type":"lookup","typeAttributes":{"displayFields":"Name","displayFormat":"Name","label":"Product2Id","lookUpObjectName":"Product2","lookupReadOnly":true,"lookUpValueId":{"fieldName":"Product2Id"},"pickListContext":{"fieldName":"Id"},"placeHolder":"Select Product"},"wrapText":true},{"editable":false,"fieldName":"TCH_Lot__c","isDatabaseRequired":false,"label":"Lot","sortable":false,"type":"lookup","typeAttributes":{"displayFields":"Name","displayFormat":"Name","label":"TCH_Lot__c","lookUpObjectName":"Lot__c","lookupReadOnly":true,"lookUpValueId":{"fieldName":"TCH_Lot__c"},"pickListContext":{"fieldName":"Id"},"placeHolder":"Select Lot"},"wrapText":true},{"editable":false,"fieldName":"TotalPrice","isDatabaseRequired":false,"label":"Total Line Proposed Turnover","sortable":false,"type":"currency","typeAttributes":{},"wrapText":true},{"editable":true,"fieldName":"Quantity","isDatabaseRequired":true,"label":"Proposed Quantity (in units)","sortable":false,"type":"number","typeAttributes":{"maximumFractionDigits":"4","minimumFractionDigits":"0"},"wrapText":true},{"editable":true,"fieldName":"UnitPrice","isDatabaseRequired":false,"label":"Proposed Price (per Unit)","sortable":false,"type":"currency","typeAttributes":{},"wrapText":true},{"editable":true,"fieldName":"Net_Net_price__c","isDatabaseRequired":false,"label":"Proposed Net Price (per Unit)","sortable":false,"type":"currency","typeAttributes":{},"wrapText":true},{"editable":false,"fieldName":"Required_quantity__c","isDatabaseRequired":false,"label":"Required Quantity (in units)","sortable":false,"type":"number","typeAttributes":{"maximumFractionDigits":"4","minimumFractionDigits":"0"},"wrapText":true},{"editable":false,"fieldName":"Max_Price__c","isDatabaseRequired":false,"label":"Max Tender Unit Price (per Unit)","sortable":false,"type":"currency","typeAttributes":{},"wrapText":true},{"editable":true,"fieldName":"Awarded_quantity__c","isDatabaseRequired":false,"label":"Awarded Quantity (in units)","sortable":false,"type":"number","typeAttributes":{"maximumFractionDigits":"4","minimumFractionDigits":"0"},"wrapText":true},{"editable":true,"fieldName":"Awarded_price__c","isDatabaseRequired":false,"label":"Awarded Price (per Unit)","sortable":false,"type":"currency","typeAttributes":{},"wrapText":true},{"editable":false,"fieldName":"Schedules__c","isDatabaseRequired":false,"label":"Delivery Split per Year","sortable":false,"type":"boolean","typeAttributes":{},"wrapText":true}];
this.tableData =[{"Product2Id":"01t7b000003tIjvAAE","TotalPrice":400,"Quantity":2,"UnitPrice":200,"Net_Net_price__c":2300,"Required_quantity__c":2,"Max_Price__c":3000,"Awarded_quantity__c":2,"Awarded_price__c":200,"Schedules__c":false,"Id":"00k7b000005xWjrAAE"}];
The sample columns and tableData are responsible for populating the data under
The Data for column and Rows is coming from Apex using a wrapper class.
I've already gone through many links and the one most helpful was - LWC datatable Header wrapping