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);


And in the controller I have this:

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


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?

1 Answer 1


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
    Commented Feb 28, 2017 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. Commented Mar 1, 2017 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. Commented Mar 1, 2017 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
    Commented Mar 1, 2017 at 13:58
  • @DougChasman Sounds a workable approach (if a little verbose). I'll do that!
    – Matt Lacey
    Commented Mar 2, 2017 at 0:51

You must log in to answer this question.

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