1

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. Custom Data Table showing lookup and Picking in inline editing

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.

Header columns overlapping

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

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.