5

Update: My Code (DX generated) is saved in a github repo with good README => here

I try to create a Lightning Component (LC) using an external js library jstree, which is jquery dependent.

Original issue

If this LC is added in partner portal home page, $A.enqueueAction has no data returned once the function is constructed inside a jquery function.

When this LC is added to other pages, such as account or contact record page, this issue does not appear, i.e. $A.enqueueAction returns well.

I thought the issue roots from jquery v.s. LC namespace conflicting, but it seems not as my troubleshooting goes.

My troubleshooting progress

The issue most likely comes from Modifying Components Outside the Framework Lifecycle.

This article has similar issue as I am having.

A similar stackoverflow question here.

Current issue

After troubleshooting, I still don't figure out the correct way to use $A.getCallback in my code.

I have used it in my controller.js (code attached below). $A.enqueueAction returns well, but a page error pops up:

This page has an error. You might just need to refresh it. Assertion Failed!: $A.getCallback(): 'callback' must be a valid Function : false

In addition, I still don't know why this issue only appears in partner portal as stated in Original issue section above.

Console screenshotenter image description here

My code below, simplified version

My Code (DX generated) is saved in a github repo with good README => here

cmp file

<ltng:require styles="/resource/ref/themes/default/style.min.css" scripts="{!join(',', '/resource/ref/jquery-3.3.1.min.js', '/resource/ref/jstree.js' )}"
afterScriptsLoaded="{!c.resourceLoaded}" />

<div id="render"></div>
</aura:component>

Controller.js (format is aligned with jstree instruction

({
  resourceLoaded: function(component, event, helper) {
    console.log("Resources loaded succesfully!");
    $("#render").jstree({
      core: {
        data: function(node, cb) {
          if (node.id === "#") {
            console.log("root node");
            cb([
              {
                text: "Document",
                children: true,
                data: {
                  uri:
                    "whatever-REST-endpoint-URL"
                }
              }
            ]);
          } else {
            console.log("sub node");
            //use $A.getCallback here, but page throws error 
            $A.getCallback(helper.getLazyResponse(component, node.data.uri, cb));
          }
        }
      }
    });
  }
});

helper.js

({
  getLazyResponse: function(cmp, url, cb) {
    var action = cmp.get("c.getStructureInfo");
    action.setParams({ URL: url });
    action.setCallback(this, function(response) {
      var state = response.getState();
      if (state === "SUCCESS") {
        var result = response.getReturnValue();
        console.log("Data: \n" + result);
        cb(JSON.parse(result));
      } else {
        console.log("error");
      }
    });
    $A.enqueueAction(action);
    console.log("ajax call fired");
  }
});

Apex controller

public with sharing class SPWebServiceController {

  @AuraEnabled
  public static String getStructureInfo(String URL){
    return 'hello';
  }
}

1 Answer 1

4

$A.getCallback needs a function; instead, you're calling a function and returning a null value. It's also not appropriate here, because you're not using a callback at the point you're trying to use $A.getCallback; you want the code in the helper to trigger immediately.

Your code should be simply:

helper.getLazyResponse(component, node.data.uri, cb);

That said, I realize you're trying to build a callback (cb), so you do actually need to get a callback handle here. Thus, your code changes to:

helper.getLazyResponse(component, node.data.uri, $A.getCallback(cb));

The data element used in jstree is itself a callback, and so needs to be wrapped up in an $A.getCallback as well:

({
  resourceLoaded: function(component, event, helper) {
    console.log("Resources loaded succesfully!");
    // var $j = jQuery.noConflict();
    $("#render").jstree({
      core: {
        data: $A.getCallback(function(node, cb) {
          if (node.id === "#") {
            console.log("root node");
            cb([
              {
                text: "Documents",
                children: true,
                data: {
                  uri:
                    "https://finxxi.sharepoint.com/sites/poc/_api/web/GetFolderByServerRelativeUrl('Shared Documents')"
                }
              }
            ]);
          } else {
            console.log("sub node");
            helper.getLazyResponse(component, node.data.uri, $A.getCallback(cb));
          }
        })
      },
      plugins: ["wholerow"]
    });
  }
});
7
  • Thanks for the explanation. I have tried to wrap cb in $A.getCallback, exactly as you proposed. Though the error is gone, the $A.enqueueAction still does not return :(..
    – Xi Xiao
    Mar 5, 2018 at 21:39
  • @XiXiao (removed prior comment). Just saw your edit. I'll try it in my org.
    – sfdcfox
    Mar 5, 2018 at 22:00
  • Thanks! I am also testing to make sure the code in repo repreduce my issue
    – Xi Xiao
    Mar 5, 2018 at 22:16
  • Repo code is tested. Issue reproducing steps are in README. Btw, this issue only appears in partner community page (details are in the repo README.md too)
    – Xi Xiao
    Mar 5, 2018 at 22:43
  • @XiXiao I'm kind of embarrassed it took me this long to see it. The data function itself needs to fire an action, so it has to be in a $A.getCallback. See edit. The $A.getCallback(cb) is optional, but doesn't hurt anything.
    – sfdcfox
    Mar 5, 2018 at 22:50

You must log in to answer this question.

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