0

I have created a lightning component that iterates over column data and row data and in between this iteration i am calling my other lightning component that basically generates data for the table. The code looks like this:

<table class="slds-table slds-table--bordered slds-table--cell-buffer slds-box" style="height;300px">
    <thead>
        <tr class="slds-text-heading--label">
            <aura:iteration items="{!v.columns}" var="ct">
                <th scope="col" class="slds-is-sortable">
                    <div class="slds-truncate" title="{!ct.label}" onclick="{!c.sortAction}">{!ct.label}</div>
                </th>
            </aura:iteration>
        </tr>
    </thead>
    <tbody>
        <aura:iteration items="{!v.data}" var="acc">
            <tr>
                <aura:iteration items="{!v.columns}" var="col">
                    <td><c:DataGrigCell data="{!acc}" column="{!col}" relatedAssociations="{!v.relatedAssociations}" relatedContacts="{!v.relatedContacts}"/></td>  
                </aura:iteration>
            </tr>
        </aura:iteration>
    </tbody>
</table>

Now i want to know how can i implement client side sorting in this table in lightning component. Any kind of help is appreciated. Thanks in advance :)

1
  • We have a very good example here and the same will apply on your sortAction call. The example is for data table but the same dynamics will apply to your component.
    – manjit5190
    May 10, 2020 at 12:50

1 Answer 1

0

You should try Lightning:DataTable with standard table features. You can use this generic component as well.

CmAp_LightningDataTable.Cmp

<aura:component >
    <!-- Attrubutes Definations Start here -->
    <aura:attribute type="boolean"
                    name="enableSearchonRow"
                    description="This attribute is used to show hide search option in tabel"/>
    <aura:attribute type="Integer"
                    name="maxRowSelection"
                    default="1"
                    description="This attribute is used to define number of row can be selected"/>
    <aura:attribute type="string"
                    name="tableHeaderTitle"
                    default=""
                    description="This attribute is used to define title for table"/>
    <aura:attribute type="List"
                    name="selectedRows"
                    description="This attribute is used to store preselected record Ids"
                    />
    <aura:attribute type="string"
                    name="panelHeightinPx"
                    default="170px"
                    description="This attribute is used to define container Height"
                    />
    <aura:attribute type="string"
                    name="headerIcon"
                    default="standard:empty"
                    description="This attribute is used to define icon in Header"
                    />
    <aura:attribute type="boolean"
                    name="showRowNumber"
                    default="false"
                    description="This attribute is used to show hide row number"
                    />
    <aura:attribute type="boolean"
                    name="showHeaderButton"
                    default="false"
                    description="This attribute is used to show hide button in Header"
                    />
    <aura:attribute type="string"
                    name="buttonLabel"
                    default="New"
                    description="This attribute is used to show label on Button"
                    />
    <aura:attribute type="string"
                    name="searchString"
                    default="false"
                    description="This attribute store search fields for row filter. Fields must be comma saperated."
                    />
    <aura:attribute name="recordSearchKey" 
                    type="string" 
                    default=""
                    description="this attribute store search string for row in table"
                    access="Private"/>
    <aura:attribute name="unFilteredData"
                    type="List"
                    description="this attribute store all data for table without filter"
                    access="Private"
                    /> 
    <aura:attribute name="lstDataRows"
                    type="List"
                    Description="attribute store Data Rows list of sobject"/>
    <aura:attribute name="lstColumns"
                    type="List"
                    Description="store Header columns property list"/> 
    <aura:attribute name="defaultSelectedRow"
                    type="string"
                    Description="store default selected row id in table"/> 
    <aura:attribute name="showSpinner"
                    type="Boolean" 
                    default ="false" 
                    access="private"/>
    <aura:attribute name="sortDirection"
                    type="String"
                    default="desc" />
    <aura:attribute name="sortedBy"
                    type="String" />
    <!-- Attrubutes Definations ends here -->
    <!-- Aura Handeler Section -->
    <aura:handler name="init" value="{!this}" action="{!c.doinit}"/>
    <aura:method name="setPredefinedValues" action="{!c.setPredefinedValues}" access="public"/>
    <!--<aura:handler name="change" value="{!v.lstDataRows}" action="{!c.setPredefinedValues}"/>-->
    <!-- Aura Handeler Section Ends here -->
    <!-- Events Regstration Sections Defiend here -->
    <aura:registerEvent name="onclickActionEvent" type="c:CmAp_LightningDataTableActionEvent"/>
    <aura:registerEvent name="onRowChangeEvent" type="c:CmAp_LightningDataTableSelectionEvent"/>
    <aura:registerEvent name="onClickRowActionEvent" type="c:CmAp_LightningDataTableRowActionEvent"/>
    <!-- Events Regstration Sections Ends here -->
    <lightning:card title="{!v.tableHeaderTitle+' ('+if(not(empty(v.lstDataRows)),v.lstDataRows.length,0)+')'}" iconName="{!v.headerIcon}" variant="base">
        <aura:set attribute="actions">
            <aura:if isTrue="{!v.enableSearchonRow}">
                <lightning:input type="search" variant=" label-hidden" class="slds-m-left_small slds-m-right_small" placeholder="{!'Search '+v.tableHeaderTitle}" value="{!v.recordSearchKey}" onchange="{!c.searchInRows}" />
            </aura:if>
            <aura:if isTrue="{!v.showHeaderButton}">
                <lightning:button class="slds-theme_neutral" variant="brand" label="{!v.buttonLabel}" onclick="{!c.handelBttonClickAction}"></lightning:button>
            </aura:if>
        </aura:set>
        <aura:set attribute="footer">&nbsp;</aura:set>
        <div style="{!if(not(empty(v.lstDataRows)),'','display:none')}">
            <div style="{!if((v.lstDataRows.length> $Label.c.CmAp_AutoHeightMaxRowLimit),'height:'+v.panelHeightinPx,'')}">
                <!-- Spinner Section -->
                <aura:if isTrue="{!v.showSpinner}">
                    <div class="slds-is-relative">
                        <lightning:spinner variant="brand" alternativeText="Loading..." />
                    </div>
                </aura:if>
                <!-- Spinner Ends Here -->
                <lightning:datatable aura:id="recordTabel"
                                     columns="{!v.lstColumns}"
                                     data="{!v.lstDataRows}"
                                     keyField="Id"
                                     selectedRows="{!v.selectedRows}"
                                     maxRowSelection="{! v.maxRowSelection }"
                                     onrowselection="{!c.updateSelectedText}"
                                     showRowNumberColumn="{!v.showRowNumber}"
                                     sortedDirection="{!v.sortDirection}"
                                     sortedBy="{!v.sortedBy}"
                                     onsort="{!c.handleSort}"
                                     wrapTextMaxLines="2"
                                     hideCheckboxColumn="{!if(v.maxRowSelection>0,false,true)}"
                                     onrowaction="{!c.rowOnClickActions}"
                                     />
            </div>
        </div>

        <div class="slds-box slds-theme_default slds-align_absolute-center" style="{!if(not(empty(v.lstDataRows)),'display:none','')}">
            <p><b>No data to display.</b></p>
        </div>

    </lightning:card>
</aura:component>

CmAp_LightningDataTableController.Js

    ({
        doinit: function(component, event, helper){
            component.set("v.showSpinner",true);

        },
        setPredefinedValues : function(component, event, helper) {
            helper.setPredefinedValues(component, event, helper);
        },
        updateSelectedText: function (component, event, helper) {
            helper.handleSelect(component, event, helper);
        },
        searchInRows: function (component, event, helper) {
            helper.searchInRows(component, event, helper);
        },
        handleSort: function(component, event, helper) {
            helper.handleSort(component, event);
        } ,
        handelBttonClickAction: function (component, event, helper) {
            helper.handelBttonClickAction(component, event, helper)
        },
        rowOnClickActions: function (component, event, helper) {
            helper.rowOnClickActions(component, event, helper)
        }
    })

**CmAp_LightningDataTableHelper.js**

({
    setPredefinedValues : function(component, helper) {
        let lstData =component.get("v.lstDataRows");
        let lstUnFilteredData = component.get("v.unFilteredData");
       // if($A.util.isUndefined(lstUnFilteredData) || $A.util.isEmpty(lstUnFilteredData)){
            component.set("v.unFilteredData",lstData);
        //}
        this.handelDefaultRowSelection(component, helper);
        component.set("v.showSpinner",false);
    },
    handelDefaultRowSelection: function(component, helper){
        let defaultSelectedRow = component.get("v.defaultSelectedRow");
        if(!$A.util.isUndefined(defaultSelectedRow) && !$A.util.isEmpty(defaultSelectedRow)){
            let temp =[];
            temp.push(defaultSelectedRow);
            let recordTabel = component.find("recordTabel");
            if(recordTabel){
                recordTabel.set("v.selectedRows", temp);            
            }
        }
    },
    searchInRows: function (component, event, helper) {
        let data = component.get("v.lstDataRows"); 
        let allData = component.get("v.unFilteredData"); 
        let strfieldlist = component.get('v.searchString');
        if(!$A.util.isUndefined(strfieldlist) && !$A.util.isEmpty(strfieldlist)){
            let fieldlList = strfieldlist.split(',');
            let searchKey = component.get("v.recordSearchKey");
            if(!$A.util.isUndefined(data) || !$A.util.isEmpty(data)){  
                let filtereddata = allData.filter(checkFieldsValidity);  
                function checkFieldsValidity(word){
                    let isValid=false;
                    for(let fieldname of fieldlList) {
                        if(word.hasOwnProperty(fieldname) && 
                           (!searchKey || word[fieldname].toLowerCase().indexOf(searchKey.toLowerCase()) > -1)){
                            isValid= true;
                            break;
                        }
                    }
                    return isValid;
                }
               component.set("v.lstDataRows", filtereddata); 
                this.handelDefaultRowSelection(component, helper);
            } 
            if(searchKey==''){  
                component.set("v.lstDataRows",component.get("v.unFilteredData"));  
            }
        }

    },
    sortBy: function(field, reverse, primer) {
        var key = primer
        ? function(x) {
            return primer(x[field]);
        }
        : function(x) {
            return x[field];
        };

        return function(a, b) {
            a = key(a);
            b = key(b);
            return reverse * ((a > b) - (b > a));
        };
    },
    handleSort: function(component, event) {debugger;
        var sortedBy = event.getParam('fieldName');
        var sortDirection = event.getParam('sortDirection');
        let data = component.get('v.lstDataRows');
        var cloneData = data.slice(0);
        cloneData.sort((this.sortBy(sortedBy, sortDirection === 'asc' ? 1 : -1)));        
        component.set('v.lstDataRows', cloneData);
        component.set('v.sortDirection', sortDirection);
        component.set('v.sortedBy', sortedBy);
    },
    handelBttonClickAction: function(component, event, helper){
        let compEvent = component.getEvent("onclickActionEvent");
        let tableUniqueName = component.get("v.tableDataType"); 
        compEvent.setParams({"tableUniqueName" : tableUniqueName });
        compEvent.fire();
    },
    handleSelect: function(component, event, helper){
        let compEvent = component.getEvent("onRowChangeEvent");
        let tableUniqueName = component.get("v.tableHeaderTitle"); 
        let selectedRows = event.getParam('selectedRows');
        compEvent.setParams({"tableUniqueName" : tableUniqueName,
                             "selectedRows":selectedRows});
        compEvent.fire();
    },
     rowOnClickActions: function (component, event, helper) {debugger;
        let compEvent = component.getEvent("onClickRowActionEvent");
        let tableUniqueName = component.get("v.tableHeaderTitle"); 
        let objRecord = event.getParam('row');
        let actionName = event.getParam('action').name;
        compEvent.setParams({"tableUniqueName" : tableUniqueName,
                             "selectedRowActionName":actionName,
                             "selectedRowData":objRecord});
        compEvent.fire();
    }
})

How To Use

<c:CmAp_LightningDataTable aura:id="genericTable"
                               tableHeaderTitle ="{!$Label.c.CmAp_DevicesHeader}"
                               panelHeightinPx="350px"
                               headerIcon="standard:planogram"
                               maxRowSelection="1"
                               showRowNumber="{!v.objWrapDevice.showRowNumber}"
                               showHeaderButton="false"
                               enableSearchonRow="{!v.objWrapDevice.enableSearchonRow}"
                               searchString="{!$Label.c.CmAp_DeviceSearchString}"
                               lstDataRows="{!v.objWrapDevice.dataForTable}"
                               lstColumns ="{!v.objWrapDevice.columnForTable}"
                               defaultSelectedRow="{!v.SelectedDeviceId}"/>
4
  • Hi Dheeraj, Thanks for this but for my requirement and type of data that i need to show in table cannot be achieved by lightning data table hence i have used custom table here. My each cell is a seperate lightning component because i had to show complex data something that we cannot achieve via lightning data table. May 10, 2020 at 14:37
  • @RakshitSegwal You can use a LWC data table, it allows you to extend it and define additional cell types with custom designs. This may be what you're looking for.
    – sfdcfox
    May 10, 2020 at 15:37
  • In lightning data table you can also define data type for each column and also do forming for each column. You can add custom action as well. There are lots of future available with solution in detail you can explore this link developer.salesforce.com/docs/component-library/bundle/… May 11, 2020 at 7:00
  • You can use the sorting method used in CmAp_LightningDataTableController.Js method name is handleSort you can call this method from any button and use for sorting. Here sortedBy variable use column name, shortdirection define sorting order and Data variable is used for List of data displayed in table May 11, 2020 at 7:03

You must log in to answer this question.

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