4

Been tearing my hair out for two days on this one, so hopefully somebody can help.

I'm using jQuery DataTables to build a formatted table of Case data. When a user clicks on a case number, I need to fire an application event that a separate tab manager component will handle, causing it to open a new tab.

The problem I'm seeing is that when I use $A.get to get the application event in the click handler itself, it's always undefined. If I use $A.get to get the event one level up and refer to that in the click handler, I can only fire the event once, and then get an error if I try to fire it a second time (for example, user clicks on another link).

I found somebody with a related issue at: Lightning Application: $A.get(event) returning undefined when called from a jQuery callback

That post is what gave me the idea to try method #2, but since I can only fire that once, I still need to find a solution. In case anybody mentions application vs component events...there are several components in this app that listen to a variety of events, so to make development easier and just concentrate on functionality, I went with using all application events so I don't have to worry about bubbling.

I would REALLY appreciate any help on this. I thought $A.get could be used "anywhere" to get Aura information, but does where it's used affect it's scope or something?

Here's some sample code showing both methods I'm trying:

test_CaseLink_App:

<aura:application >
    <ltng:require styles="{!$Resource.SLDS213 + '/assets/styles/salesforce-lightning-design-system-ltng.min.css'}"/>

    <div class="scopedcompanyname-slds">
        <c:test_CaseLink />
    </div>
</aura:application>

test_CaseLink.cmp:

<aura:component>
    <ltng:require scripts="{!join(',',
                                  $Resource.jquery300, 
                                  $Resource.datatables11012_with_images + '/js/datatables.min.js',
                                  $Resource.datatables11012_with_images + '/js/fixedheader.datatables.min.js')}"
                  styles="{!join(',',
                                 $Resource.datatables11012_with_images + '/css/datatables.min.css',
                                 $Resource.datatables11012_with_images + '/css/fixedheader.datatables.min.css')}"
                  afterScriptsLoaded="{!c.scriptsLoaded}"/>

    <!-- Custom event registrations -->
    <aura:registerEvent name="tabEvent" type="c:caseMgt_Event_Tab"/>

    <div>
        <table id="relatedCasesTable" class="display cell-border"/>
    </div>

</aura:component>

test_CaseLinkController.js:

({
    scriptsLoaded : function(component, event, helper) {
        helper.formatTable(component, helper);
    },

})

test_CaseLinkHelper.js:

({
    formatTable: function(component, helper) {
        var cases = [{"Id"         : "500i000000iCuzI",
                      "CaseNumber" : "00007640",
                      "Subject"    : "Subject for 7640"
                     },
                     {"Id"         : "500i000000iCv1Y",
                      "CaseNumber" : "00007641",
                      "Subject"    : "Subject for 7641"
                     },
                     {"Id"         : "500i000000iCv1d",
                      "CaseNumber" : "00007642",
                      "Subject"    : "Subject for 7642"
                     },
                    ];

        jQuery('#relatedCasesTable').DataTable({
            data          : cases,
            dom           : "<fip<t>>",
            order         : [[0, "asc"]],
            columns       : [
                {data  : 'CaseNumber',
                 title : 'Case Number',
                 render : function(data, type, row, meta) {
                     if (type == 'display') {
                         return '<a id="caseLink" data-caseId="' + row.Id + '">' + data + '</a>';
                     }
                     else if (type == 'filter') {
                         return data;
                     }
                     else {
                         return data;
                     }
                 },
                 createdCell : function createdCellCallback(cell, cellData, rowData, rowIndex, colIndex) {
                     jQuery('#caseLink', cell).each(function eachCaseLinkCallback() {
                         var outerTabEvent = $A.get('e.c:caseMgt_Event_Tab');
                         console.log('DEBUG: (eachCaseLinkCallback) outerTabEvent = ' + outerTabEvent);

                         this.addEventListener('click', function caseLinkClicked(event){
                             // Run using either METHOD 1 or 2 below (make sure one is commented):

                             // METHOD 1 - is always undefined
                             var tabEvent = $A.get('e.c:caseMgt_Event_Tab');

                             // METHOD 2 - can only fire once
                             //var tabEvent = outerTabEvent;

                             var caseId   = event.currentTarget.getAttribute('data-caseId');
                             console.log('DEBUG: (caseLinkClicked) tabEvent = ' + tabEvent);
                             console.log('DEBUG: (caseLinkClicked) caseId   = ' + caseId);

                             tabEvent.setParams({"tabset"                   : "main",
                                                 "objectId"                 : caseId,
                                                 "eventType"                : "addTab",
                                                 "addTabActivateAfterwards" : false});
                             tabEvent.fire();
                         });
                     });
                 }
                },              
                {data  : 'Subject',
                 title : 'Subject'
                }
            ],
        });

    },

})

CaseMgt_Event_Tab.evt:

<aura:event type="APPLICATION" description="Tab event">
    <aura:attribute name="tabset"                   type="String"  default=""/>
    <aura:attribute name="objectId"                 type="Id"      default=""/>
    <aura:attribute name="eventType"                type="String"  default=""/>
    <aura:attribute name="addTabActivateAfterwards" type="Boolean" default="false"/>
</aura:event>

Thanks!

  • Not sure if exactly related but I grabbed an event, enqueued an action, in the callback I enqueued another action and in the second callback I attempted to reference the event I grabbed in the main part of the function. It returned undefined as well. I ended up have to grab the event again in the second callback....I'll admit I am no expert so not even sure if that is what is going on with you, just sharing my observation after pulling my hair out. – Eric Feb 1 '17 at 2:11
  • @Florissant53 What happens if you place var outerTabEvent = $A.get('e.c:caseMgt_Event_Tab'); line is above the jQuery('#relatedCasesTable').DataTable({..}) – Praveen Feb 1 '17 at 6:26
10

Wiring up external event handlers (those that are invoked outside of the Lightning event/action lifecycle) requires the use of $A.getCallback() to correctly re-establish the Lightning context.

See https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/js_cb_mod_ext_js.htm for more details.

Basically wrap caseLinkClicked before it is sent to addEventListener():

this.addEventListener("click", $A.getCallback(function caseLinkClicked() { ... })
  • You are welcome - please don't forget to vote up my answer :-) – Doug Chasman Feb 1 '17 at 22:58
  • Thanks to both of yall. Converting an Aura:Iteration to a Datatable, and ran into this exact issue. – ATA1k Jun 29 '17 at 19:00

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.