4

Say I need to use afterRender on the <aura:component> to modify the DOM after it's been rendered (assuming afterRender actually works). To do that modification I need to use a third party library which I'm loading from a static resource. With a naïve setup, I'd just try and use the library, and I'd more than likely encounter an error along the lines of:

d3 is not defined

No bonus points for guessing which library I'm using.

Current Workaround

What I'm doing right now is nasty. In the component I have two attributes and the JS include:

<aura:attribute name="rendered" type="Boolean" default="false"/>
<aura:attribute name="d3Loaded" type="Boolean" default="false"/>

<ltng:require scripts="{!$Resource.D3}" afterScriptsLoaded="{!c.doInit}"/>

In afterRender in the component's renderer I have this:

component.set("v.rendered", true);

if(component.get("v.d3Loaded"))
    helper.doMyStuff(component);

And in the controller I have this:

doInit : function(component, event, helper)
{
    component.set("v.d3Loaded", true);

    if(component.get("v.rendered"))
        helper.doMyStuff(component);
},

Nasty stuff eh?

The Question

So is there a proper pattern for dealing with this scenario, whereby I can reliably use a third party library after the component has been rendered?

4

Matt you should not have to resort to anything more than using afterScriptsLoaded= which is specifically designed to automatically coordinate both asynchronous loading of libraries (in order) and the rendering lifecycle of Lightning. Basically, ltng:require is doing something similar to the rendezvous logic you've implemented by hand under the covers and the expected pattern is to put your code entirely in the afterScriptsLoaded= handler.

I use D3 (v3 modified in 1 location to be strict mode compliant and v4 OOTB) without resorting to any "nasty stuff". Are you seeing d3 undefined all the time or is it intermittent? I've never had an issue with this library specifically but some libraries are not really initialized (e.g. they load other scripts dynamically themselves) by the time the script.onload event is fired which is 50% of what afterScriptsLoaded= relies on.

Please open a support case on this with specific repro info so we can get someone to dig into it.

  • Thanks for the info Doug! It does seem to be intermittent. I don't know if this affects things, but I have a hierarchy of two components, both of which use D3 from the same resource, and it's in the child where I hit the issue. Will try and generate a solid reproduction case. – Matt Lacey Feb 28 '17 at 22:43
  • @MattLacey do both components include the complete set of ltng:require tags for all of the libraries they depend on (they should)? ltng:require also handles once and only once loading semantics. ltng:require cannot coordinate afterScriptsLoaded and the render lifecycle across components that implicitly depend on a library. Ideally each component is meant to be independent and declare all of its dependencies to be testable, not suffer from timing issues, etc. – Doug Chasman Mar 1 '17 at 11:08
  • 1
    I often create a component that just has my ltng:require's in it then include that component in the components that need a library set. I alos expose the afterScriptsLoaded on that helper component to allow me to easily wire up my logic. – Doug Chasman Mar 1 '17 at 11:08
  • 2
    Hi @DougChasman I assume that, in the method you suggested afterScriptsLoaded would trigger a controller or helper call which in turn initialises D3 which involves DOM manipulation. So this scenario makes the DOM manipulation outside the rendering lifecycle which is not a suggested practice as per the developer guide. So should we not depend on the renderer or is it ok to do it directly from the afterScriptsLoaded as you suggested? – SE_User Mar 1 '17 at 13:58
  • @DougChasman Sounds a workable approach (if a little verbose). I'll do that! – Matt Lacey Mar 2 '17 at 0:51

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.