[SalesForce] How to add waiting time in lightning component controller

I used setTimeout() of javascript, and my code to be executed is also is getting executed, but somehow the $A.util.removeClass and $A.util.addClass are not working and my component(i.e a Toast written in slds markup) to be hidden is not getting hidden. Is there any known workaround?

Controller method:

addDelay : function(component, event, helper){
    var delay=4000; //4 seconds
    setTimeout(function() {
        console.log('Inside delay: ');
        var toastDiv= component.find('toastDiv');
        console.log('toastDiv:  '+ toastDiv);
        $A.util.removeClass(toastDiv, "slds-show");
        $A.util.addClass(toastDiv, "slds-hide");
    }, delay);

Here, toastDiv is the ID of div element of Toast component markup.

Output of console:
SecureComponent: markup://aura:html {289:0} {toastDiv}{ key: {"namespace":"c"}

which means it is fetching the div correctly.

UPDATED CODE FOR REFERENCE:

        window.setTimeout(
        $A.getCallback(function() {
            if(component.isValid()){
                var toastDiv= component.find('toastDiv');
                $A.util.removeClass(toastDiv, "slds-show");
                $A.util.addClass(toastDiv, "slds-hide");
            }
            else{
                console.log('Component is Invalid');
            }
        }), 3000
    );

Best Answer

setTimeout() as a "fix" for timing issues is rarely a good choice - just moves the indeterminacy to another place /or adds lag (4 seconds is an eternity). The correct way to handle this is with either data binding to myDiv's v.class attribute (best) or in a custom renderer.

Setting that aside it's also critical to note that myDiv is actually a component and not an element (Component.find() always works st the component api level). The remove/addClass() util methods are also operating at the component level (they manipulate the v.class attribute). Why does this matter? By introducing a callback using setTimeout() you have also introduced code execution outside of Lightning's visibility and any time this is fine you need to wrap your callback with a call to $A.getCallback() to allow Lightning to restore context and also run its event/render lifecycle. Without $A.getCallback() Lightning does not know to even look to see that you have change myDiv.v.class and therefor does not update the corresponding DOM element's classList.

See Modifying Components Outside the Framework Lifecycle https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/js_cb_mod_ext_js.htm for more info - but like I said please reconsider your approach entirely and switch to a simpler declarative (value binding to an attribute on your component that contains myDiv) approach and let Lightning handle the timing etc.

Related Topic