7

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!

2
  • 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
    Commented Feb 1, 2017 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
    Commented Feb 1, 2017 at 6:26

2 Answers 2

11

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() { ... })
2
  • You are welcome - please don't forget to vote up my answer :-) Commented Feb 1, 2017 at 22:58
  • Thanks to both of yall. Converting an Aura:Iteration to a Datatable, and ran into this exact issue.
    – ATA1k
    Commented Jun 29, 2017 at 19:00
1

You can try to add access="global" to event declaration:

<aura:event type="APPLICATION" access="global">

You must log in to answer this question.

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