9

I'm trying to load jquery and use it for dom manipulation. Therefore I need to find the right place to invoke the $() call.

In the component, I load jquery like this

<ltng:require scripts="{!$Resource.elfJquery_js}" />

In the renderer (knowing I have a div), my code is

afterRender: function (cmp, helper) {
    var afterRend = this.superAfterRender();
    $("div").addAttr('test'); 
    return afterRend;
},

It seems to happen, that jquery is not loaded at the time afterRender() is executed. I got errors, that $ is not defined. I assume due to async loading done by ltng:require. Is there any easy way to make sure libs are loaded at the time of first afterRender() or any other place to put scripts which needs to process the finaly generated markup?

  • You can do that with vanilla JS youmightnotneedjquery.com – Caspar Harmer Dec 26 '16 at 20:09
  • @CasparHarmer I'm aware of that but decided against. You can do everything in vanilla JS, because jquery (and frankly all JS libs out there) are vanilla JS. However using them makes you more efficient. Here execution speed might go down and resource consumption up. But using jquery regardless of that always paid off for me so big that I don't write any single line of DOM manipulation without it. The pros are: shortness, readability, maintenability in the long run. – Uwe Heim Dec 27 '16 at 8:02
  • Putting your code in the callback of ltng:require's afterScriptsLoaded should be sufficient. – TrevorBliss Jan 6 '17 at 22:01
10

As per @TrevorBliss comments , adding afterScriptsLoaded to the ltng:require is sufficient which means there's no need for the renderer.

If you really need to do this in the renderer, then you need to do below:

  1. Use rerender instead of afterRender.
  2. Have a flag to indicate the script has been loaded and set it's value to true in afterScriptsLoaded method of ltng:require.

What would have happen here is:

  1. Component loads and it's init handler will fire(if you have one).

  2. Frameworks finishes the rendering the DOM in the browser.

  3. ltng:require's afterScriptsLoaded method will be called which in turn sets an aura:attribute value to true, thus causing the framework to run the rerender method of the component.

So our best choice is, to use rerender because it is called after the afterRender which in turn guarantees availability of DOM and also we are 100% sure that scripts are loaded(since it is invoked due the flag setting).

Be cautious when using rerender method, becauses it is called many times during the component's lifecycle. Generally it will be called, whenever you change the value of an aura:attribute.

Here's a sample component to demonstrate the flow:

Component:

<aura:component>
    <ltng:require scripts="{!$Resource.Jquery_js}" afterScriptsLoaded="{!c.setScriptLoaded}"/>
    <aura:attribute name="isJqueryLoaded" type="Boolean" description="Flag to indicate jquery is loaded"/>
    <aura:attribute name="needToProcessReRenderLogic" type="Boolean" description="Flag to indicate need to process the logic rerender since it is called many times during the component's lifecycle"/>
<aura:component>

Controller:

({
    "setScriptLoaded" : function(cmp){
        cmp.set("v.isJqueryLoaded",true);
        cmp.set("v.needToProcessReRenderLogic",true);
    }
})

Renderer:

({
    rerender : function(cmp, helper){
        this.superRerender();

        if(cmp.get("v.isJqueryLoaded") && cmp.get("v.needToProcessReRenderLogic")) {
            //your logics

            //Finally set the needToProcessReRenderLogic to false, since rerender will be called multiple times
            cmp.set("v.needToProcessReRenderLogic",false); // this will not fire rerender again
        }
    }
})
  • 2
    afterScriptsLoaded will wait for the components afterRender function to be called. If this is not the case there is a bug and I would like to see the repro for it to investigate. – TrevorBliss Jan 6 '17 at 22:02
  • 1
    @TrevorBliss I had this issue earlier, but i tried to reproduce this now and it works the way you said. I'll amend my answer. – Praveen Jan 8 '17 at 7:59

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.