3

I have a lightning:buttonIcon, on click of which I want it to be change to buttonIcon of some other type and its onclick action method should also change.

Markup:

<lightning:buttonIcon aura:id="downIcon"
                      iconName="utility:down"
                      variant="bare" 
                      alternativeText="Settings" 
                      iconClass="dark" 
                      class="slds-button slds-input__icon slds-text-color--default"
                      onclick="{!c.openDropdown}"/>

Controller:

openDropdown: function(component, event, helper){
    var iconID=component.find('downIcon');
    iconID.set('v.iconName', 'utility:close');    //Working
    iconID.set('v.onclick',component.getReference('c.showDefaultValue')); //Not working
}

Here i have used the logic for dynamically giving name of method to component as mentioned here: https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/js_cb_dynamic_cmp_async.htm

When I click the buttonIcon, it is giving me error :

Assertion Failed!: Unable to set value for key 'c.openDropdown'. Value provider does not implement 'set(key, value)'. : false

As I can change the "iconName" property of lightning:buttonIcon from controller, how can I similarly change method name of "onclick" property?

  • One way is to get the iconName that is set and using if else, call appropriate method. But I want to know for the sake of knowledge that how can we assign method name to "onclick" property dynamically. – Sarang Feb 28 '17 at 11:59
  • I am intrigued by this post, and i did something similar to this with custom events .. developer.salesforce.com/docs/atlas.en-us.lightning.meta/… .. Not sure if this would help – StormBr34ker Feb 28 '17 at 12:05
  • @Sumuga : The link that you gave creates dynamic handler for a component, but I am still not sure how to set method name this way or any other... – Sarang Feb 28 '17 at 12:16
  • Like i stated earlier, the dynamic handler would work for custom events not sure how to implement the same in your scenario. Lets wait for another pair of eyes to take a look :) – StormBr34ker Feb 28 '17 at 12:19
3

Hope it is not too late, I did some digging on my own and did not find enough evidence to set dynamic javascript methods using the set() method. Even returning concrete references did not help in this case. So here is my theory

When we use

iconID.set('v.onclick',component.getReference('c.showDefaultValue'));

We get the following error

Error

As it states "Value provider does not implement set(key,value)", It looks like the set property is not available for the onclick attributes. Maybe it is working as designed. Salesforce does not want us to implement it this way.

Solution :

In our scenario, as you suggested earlier you could use an if-else condition to perform your logic. But it looks messy, you would have to go through 2 methods (openDropdown & showDefaultValue ) every time some-one clicks, and this would add complexity to the logic. Hence I propose the following one.

Use Dynamic Components instead of setting the values. It works kinda similar to the set() approach that you used.

Component :

<div aura:id="container" class="container">
    <lightning:buttonIcon aura:id="downIcon"
                  iconName="utility:down"
                  variant="bare" 
                  alternativeText="Settings" 
                  iconClass="dark" 
                  class="slds-button slds-input__icon slds-text-color--default"
                  onclick="{!c.openDropdown}"/>
</div>

Controller :

    ({
    openDropdown : function(component, event, helper) {
        console.log("**** Inside openDropdown method ****");

        $A.createComponent(
            "lightning:buttonIcon",
            {
                "aura:id": "closeIcon",
                "iconName": "utility:close",
                "variant": "bare",
                "alternativeText": "Close me",
                "iconClass" : "dark",
                "class" : "slds-button slds-input__icon slds-text-color--default",
                "onclick": component.getReference("c.showDefaultValue")
            },
            function(newButton){
                var divComponent = component.find("container");
                divComponent.set("v.body",newButton);
            }
        );


    },
    showDefaultValue : function(component,event,helper){
        console.log("**** Inside showDefaultValue method ****");
    }
})

Results :

Lightning button before clicking

Step1

Lightning button after clicking, it enters the opendropdown method

Step2

Finally, when clicking on the close button, it enters showDefaultValue methd without entering the opendropdown method. This approach kind of works in the same as your component.set() logic but in addition, it creates a dynamic component and sets the v.body attribute of the outer container to the newly created component.

Step3

  • Thanksk for the elaborate answer. I think I agree with you regarding "Salesforce does not want us to implement it this way", probably that's how it is. – Sarang Mar 10 '17 at 7:18

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.