I got a lightning:datatable where I also have a search input field to search for whatever the user types in the input field. I can't get this to work together with an infinite scrolling table. Wonder if someone can help me out. If I have infinitescrolling enabled, the filter functionality does not work (I assume because the table keeps re-rendering when I type into the input field)

My markup:

<extends="c:Base" controller="AccountBrowserForm">
<aura:handler name="init" value="{! this }" action="{! c.doInit }"/>
<aura:attribute name="selectedAccountId" type="Id" access="public" />
<aura:attribute name="accounts" type="List"/>
<aura:attribute name="mycolumns" type="List"/>
<aura:attribute name="sortedBy" type="String" />
<aura:attribute name="sortedDirection" type="Boolean" default="true" />
<aura:attribute name="backingdata" type="List" /> <!-- backing data to allow a narrowed down datatable -->
<aura:attribute name="filter" type="String" /> <!-- filter input -->
<aura:registerEvent name="AccountFilterChange" type="c:AccountFilterChange" />

<aura:attribute name="enableInfiniteLoading" type="Boolean" default="true"/>
<aura:attribute name="initialRows" type="Integer" default="5"/>
<aura:attribute name="rowsToLoad" type="Integer" default="1"/>
<aura:attribute name="totalNumberOfRows" type="Integer" default="5"/>
<aura:attribute name="loadMoreStatus" type="String" default=""/>
<aura:attribute name="rowNumberOffset" type="Integer" default="0"/>
<aura:attribute name="currentCount" type="Integer" default="10"/>

<div class="forminput">
<lightning:input type="text"
                 placeholder="{!$Label.c.Searchfield_Placeholder}" />
<lightning:datatable aura:id="lightningTable"
                     data="{! v.accounts }"
                     columns="{! v.mycolumns }"
                     onrowaction="{! c.handleRowAction }"

                     loadMoreOffset="{! v.loadMoreOffset }"
                     onloadmore="{! c.loadMoreData }"

{! v.loadMoreStatus }


doInit: function (component, event, helper) {
    helper.callServer(component, "c.getAccounts", $A.getCallback(function (response) {
        component.set("v.accounts", response);
        component.set("v.backingdata", response); // Need to fetch a copy because we use this when we filter the data.
        component.set('v.mycolumns', [{
                type: "button",
                typeAttributes: {
                    label: '',
                    iconName: 'utility:add',
                    name: 'selectRecord',
                    title: 'selectRecord',
                    disabled: false,
                    value: 'edit',
                    variant: {
                        fieldName: 'variantValue'
            {label: $A.get("$Label.c.Name"), fieldName: 'Name', type: 'text', sortable: true},
            {label: $A.get("$Label.c.Street"), fieldName: 'BillingStreet', type: 'text', sortable: true},
            {label: $A.get("$Label.c.Postal_Code"), fieldName: 'BillingPostalCode', type: 'text', sortable: true},
            {label: $A.get("$Label.c.City"), fieldName: 'BillingCity', type: 'text', sortable: true},
            {label: $A.get("$Label.c.Country"), fieldName: 'BillingCountry', type: 'text', sortable: true},

filter: function (component, event, helper) {
    var data = component.get("v.backingdata"),
        term = component.get("v.filter"),
        results = data, regex;
    try {
        regex = new RegExp(term, "i");
        // filter checks each row, constructs new array where function returns true
        results = data.filter(row => regex.test(row.Name) ||
        regex.test(row.BillingStreet) ||
        regex.test(row.BillingPostalCode.toString()) ||
        regex.test(row.BillingCity) ||
    catch (e) {
        // invalid regex, use full list
    component.set("v.accounts", results);

loadMoreData: function (cmp, event, helper) {
        //Display a spinner to signal that data is being loaded
        event.getSource().set("v.isLoading", true);
        //Display "Loading" when more data is being loaded
        cmp.set('v.loadMoreStatus', 'Loading');
        helper.fetchData(cmp, cmp.get('v.rowsToLoad'))
            .then($A.getCallback(function (data) {
                if (cmp.get('v.accounts').length >= cmp.get('v.totalNumberOfRows')) {
                    cmp.set('v.enableInfiniteLoading', false);
                    cmp.set('v.loadMoreStatus', 'No more data to load');
                } else {
                    var currentData = cmp.get('v.accounts');
                    //Appends new data to the end of the table
                    var newData = currentData.concat(data);
                    cmp.set('v.accounts', newData);
                    cmp.set('v.loadMoreStatus', '');
               event.getSource().set("v.isLoading", false);


fetchData: function(component , rows){
        return new Promise($A.getCallback(function(resolve, reject) {
            var currentDatatemp = component.get('c.getAccounts');
            var counts = component.get("v.currentCount");
            currentDatatemp.setCallback(this, function(a) {
                var countstemps = component.get("v.currentCount");
                countstemps = countstemps+component.get("v.initialRows");

    } ,

Appreciate your help


Hope you have figured this out by now @erikvm :-)

For other viewers, have a look at this very helpful page:


Also, the fetchData function, which is missing from the 'Documentation' tab, is shown on the 'Example' tab:

lightning:datatable documentation

enter image description here

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.