[SalesForce] Jquery selector is not working properly in subsequent loads in lightning component

I have a lightning component which set a div's background color to red in the doInit method using jquery,is added as an lightning tab.

When i visit the tab in lightning experience for the first time, the component is loaded,div's bg color is properly set to red.But when i navigate to few tabs and come back to the above tab.

doInit is fired but the jquery is not setting the backgroud color of the div.

While debugging i found out the selector $('#TestDiv') (i.e jquery element object) logged in dev console is different for subsequent loads when compared with the first log,which seems odd.

I suspect this is because of the second or more the time the tab is visited, component definition from the cache is loaded,which inturn alters dom structure i suppose(i may be wrong)so that jquery fails to retrieve the proper dom element(which it did the first time the component was loaded).

Here's my code:

TestCmp.cmp

<aura:component implements="force:appHostable" access="public">
    <ltng:require scripts="/resource/FullCalendar/FullCalendar/jquery-1.8.2.min.js"  />
    <aura:handler name="init" action="{!c.doInit}" value="{!this}" />

    <div id="testDiv" style="height:100px;">
        test div txt
    </div>
</aura:component>

TestCmpController.js

({
    doInit:function(cmp,evt,helper){
        console.log('setting bg:::')
        $('#testDiv').css('background-color', 'red');
        console.log('done setting bg:::')
    }
})

— UPDATE —

As @ratan mentioned ,i am aware of the lightning component's api method to modify the styles.
I tried to debug the cause of the issue mentioned here while doing so i found a issue in retrieving the dom element using jquery on subsequent loads ,so i built an above component to explain the issue.

Best Answer

There are a few issues in your example:

  • init is not synchronized in any way with dynamic loading of javascript or rendering which is why <ltng:require afterScriptsLoaded="{!c.yourAfterScriptLoadedHandler}"> exists (it handles both of those challenges by sequencing one or more script onload events and the rendering lifecycle of lightning).

  • init handlers are called long before rendering happens which means that there is a timing issue there too.

  • S1/LEX has built in tab content caching (I believe it hold on to the last 5 tabs' content) and init is only called once in a component's lifecycle (right after creation)

  • manipulating DOM elements that are created on your behalf by the framework puts you at odds with the auto rerendering process and direct CSS modifications are likely to be unceremoniously overwritten. If you really need to do this it should be done in afterRender()