1

In my component, if the resources (jquery,DataTable) load before the enqueueAction (asynchronous) finishes, my Data table displays the following:

enter image description here

If the enqueueAction finishes before the resources load, the table works correctly. Is there a good way to ensure that the resources don't load until after the enqueueAction OR to redraw the element once the enqueueAction has finished so that the table doesn't indicate it is empty? Here is my code:

Controller

({
jqueryLoaded: function (component, event, helper){

    $('#example').ready(function() {
         $('#example').DataTable({
         });  
     } );
    console.log('jquery loaded');
},

doInit: function(component, event, helper) {

    var updateSols = component.getEvent("updateSolutions");
    updateSols.fire();

},

pullSolutions: function(component, event, helper) {

    var solAction = component.get("c.getSolutions");
    solAction.setCallback(this, function(response) {
        var state = response.getState();
        if (component.isValid() && state === "SUCCESS") {
            console.log(state);
            component.set("v.solutions", response.getReturnValue());  
        }
        else {
            console.log("Failed with state: " + state);
        }
    });

    $A.enqueueAction(solAction); 

},

})

Component

<ltng:require scripts="{!$Resource.jQuery224 + ',' + $Resource.DataTable}" afterScriptsLoaded="{!c.jqueryLoaded}"/>

<aura:registerEvent name="updateSolutions" type="c:UpdateSolutionsEvent"/>
<aura:handler name="updateSolutions" event="c:UpdateSolutionsEvent" action="{!c.pullSolutions}"/>
<table id="example" class="slds-table slds-table--bordered slds-table--cell-buffer">
      <thead>
        <tr class="slds-text-title--caps">
          <th scope="col">
            <div class="slds-truncate" title="Solution Number">Number</div>
          </th>
          <th scope="col">
            <div class="slds-truncate" title="Solution Name"> Name</div>
          </th>
        </tr>
      </thead>
      <tbody>
        <aura:iteration items="{!v.solutions}" var="sol">
            <tr class="slds-hint-parent">
                <th class="slds-size--1-of-5" scope="row"><a class="slds-text-link" href="{!'submit-inquiry?id=' + sol.Id}">{!sol.SolutionNumber}</a></th>
                <td class="slds-size--4-of-5">
                    <div class="slds-truncate">{!sol.SolutionName}</div>
                </td>
            </tr>
        </aura:iteration>
      </tbody>
    </table>
0

1 Answer 1

3

I tried my hand at this and this is what I have, I think the afterRender and rerender are the places where you have work your magic. I put in a spinner component to show the the server side controller is being queried.

  • I tried to create a account data table and used the afterrender and rerender to hide and show the table as needed.

My understanding is that the rerender component gets called when the component state changes, so I think this approach should work since I hide the table on afterrender and display on rerender. Now the value of attribute {!v.Accounts} is going to be set only on state = success, so even if the state results in error / incomplete the table will not be displayed since we killed it from display on afterRender.

Component:

    <aura:component controller="pressmeController">
    <aura:method name="hideSpin" action="{!c.hideSpinner}"/>
    <aura:method name="showSpin" action="{!c.showSpinner}"/>
    <aura:method name="callserver" action="{!c.callserverfunction}"/>

    <aura:attribute name="Accounts" type="Account[]" />

    <aura:handler event="aura:waiting" action="{!c.showSpinner}"/>
    <aura:handler event="aura:doneWaiting" action="{!c.hideSpinner}"/>
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>


    <center>
        <ui:spinner aura:id="spinner"/>
    </center>


    <table id="example" class="slds-table slds-table--bordered slds-table--cell-buffer">
        <thead>
            <tr class="slds-text-title--caps">
                <th scope="col">
                    <div class="slds-truncate" title="S.No">S.no</div>
                </th>

                <th scope="col">
                    <div class="slds-truncate" title="Account Id">Account Id</div>
                </th>

                <th scope="col">
                    <div class="slds-truncate" title="Account Name"> Account name </div>
                </th>

            </tr>
        </thead>
        <tbody>
            <aura:iteration items="{!v.Accounts}" var="sol" indexVar="sno">
                <tr class="slds-hint-parent">
                    <td class="slds-size--1-of-5">{!sno}</td>
                    <th class="slds-size--1-of-5" scope="row"><a class="slds-text-link" href="{!'submit-inquiry?id=' + sol.Id}">{!sol.Name}</a></th>
                    <td class="slds-size--4-of-5">
                        <div class="slds-truncate">{!sol.Name}</div>
                    </td>
                </tr>
            </aura:iteration>
        </tbody>
    </table>
</aura:component>

Controller:

({
    doInit: function(component, event, helper) {
        component.callserver(component, event, helper);
    },
    callserverfunction : function(cmp, event, helper) {    
        var action = cmp.get("c.queryAccount");

        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                cmp.hideSpin(cmp, event, helper);
                cmp.set("v.Accounts",response.getReturnValue());
            }
            else if (state === "RUNNING") {
                cmp.showSpin(cmp, event, helper);
            }
                else if (state === "ERROR") {
                    var errors = response.getError();
                    if (errors) {
                        if (errors[0] && errors[0].message) {
                            alert("Error message: " + 
                                  errors[0].message);
                        }
                    } else {
                        console.log("Unknown error");
                    }
                }
        });
        $A.enqueueAction(action);
    },
    showSpinner : function (component, event, helper) {
        var spinner = component.find('spinner');
        var evt = spinner.get("e.toggle");
        evt.setParams({ isVisible : true });
        evt.fire();    
    },
    hideSpinner : function (component, event, helper) {
        var spinner = component.find('spinner');
        var evt = spinner.get("e.toggle");
        evt.setParams({ isVisible : false });
        evt.fire();    
    }
})

Apex Controller:

public class pressmeController {

    @AuraEnabled
    public static List<account> queryAccount() {

        return [select id,Name from account limit 200];
    }

}

Renderer:

({
    afterRender : function(cmp, helper) {
        this.superAfterRender();;

        var isEmpty = $A.util.isEmpty(cmp.get("v.Accounts"));
        if(isEmpty){
            var tableid = document.getElementById('example');
            tableid.style.display = "none";
        }  

    },
    rerender : function(cmp, helper){
                this.superRerender();
        var isEmpty = $A.util.isEmpty(cmp.get("v.Accounts"));
        if(!isEmpty){
            var tableid = document.getElementById('example');
            tableid.style.display = "table";
        }
    }
})

Output:

The afterrender hides the table if the account attribute is empty and displays it back on rerender based on the account attribute.

enter image description here

3
  • Thanks for the response. I implemented your code but I still get a row that says No Data Available. It's an issue when the jQuery loads before the action finishes running, the table is seen as having no data.
    – Alex
    Nov 3, 2016 at 13:29
  • It seems like an issue related to the DataTable.js framework itself.
    – Alex
    Nov 3, 2016 at 13:35
  • @Alex Instead of using afterLoadingResources can you not use beforeLoadingResources and load the component and then load the resource to priorotize component loading then load the jquery???
    – Rao
    Nov 3, 2016 at 17:09

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.