2

Thanks to help here I have successfully made a button disappear on click.

However, I'm not yet successful controlling css using aura:handler init methods.

Repro: 1) Created this component 2) Loaded tab with the component

Expected: Alerts fire & ui:button is invisible due to display: none applied

Actual: Alerts fire but ui:button is visible and display remains inline-block

Component

<aura:component implements="force:appHostable" controller="updateUsingLightningCheckboxController">
<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
<ui:button label="Activate" press="{!c.onActivate}" aura:id="Activate"/>
</aura:component>

JS Controller:

({

doInit: function(cmp) {

    alert('fired');
    //This does not work:
            var cmpTarget = cmp.find("Activate");
            $A.util.addClass(cmpTarget , 'invisible');
    alert('fired after activate');

},

onActivate: function(cmp, evt, helper){}
//This works
            var cmpTarget = cmp.find("Activate");
            $A.util.addClass(cmpTarget , 'invisible');
})

CSS:

.THIS.invisible {
display: none;
}

3 Answers 3

6

The answers are correct as to why you're seeing the issue you're seeing. But I don't think that overriding a renderer is the right approach. If you want your button invisible onInit then you should set that in CSS and it should be invisible by default.

The best practice for hide/show is to have a class bound to an attribute in your component like this:

<aura:component>
  <aura:attribute name="isButtonShown" type="Boolean" default="false" />

  <ui:button class="{!v.isButtonShown ? 'visible' : 'hidden'}" />
</aura:component>

And in your controller:

onActivate: function(cmp, event, helper) {
  cmp.set('v.isButtonShown', true);
}
2
  • I do agree the ideal solution for OP's case is aura:attribute way rather than custom renderer which is emphasized in the answer.
    – Praveen
    Nov 17, 2016 at 18:31
  • I had missed that @Praveen yes you did say that. Nov 17, 2016 at 19:43
2

The init method is fired before DOM rendering, so your Javascript will be unable to change the attributes of the button as it will not have been rendered to the DOM at this point in the lifecycle.

Use the init event to initialize a component or fire an event after component construction but before rendering

From: https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/js_cb_init_handler.htm

You would need to perform your CSS changes in the aura:doneRendering stage of the lifecycle. See: https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/ref_aura_doneRendering.htm

2

As @MarkKeats points out, init handler is called long before DOM is rendered in the view, that's why changes in the init was not applied. But the problem with aura:doneRendering is that it will be called multiple times as part of the component's lifecycle.

There are few ways you can fix this:

1.Have an aura:attribute to hold the class and bind it to <ui:button /> component's class attribute:

<aura:attribute name="btnCls" type="String" description="class to be applied to ui:button "/>

<ui:button label="Activate" press="{!c.onActivate}" aura:id="Activate" class="{!v.btnCls}"/>

Controller.js

doInit: function(cmp) {

    alert('fired');
    //This will work
    cmp.set("v.btnCls","invisible"); // set the class as mentioned above
    alert('fired after activate');
},

2.Using custom Renderer, because it guarantees the availability of the DOM when the renderer methods are executed.

For your case, the ideal place to put the logic in afterRender() of Renderer :

afterRender: function (cmp, helper) {
    this.superAfterRender();
    var cmpTarget = cmp.find("Activate");
    $A.util.addClass(cmpTarget , 'invisible');
},

Even the doc recommends same:

There are often better alternatives to creating a custom renderer. Consider using an expression in the markup instead of setting a DOM element directly.

Personally I would go with Option 1, if the use case is relatively simple.

You must log in to answer this question.

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