[SalesForce] Dynamically changing variant and iconName on lightning:button when clicked

I restructured my table a bit and my previous actions broke. However, I wish to have the currently clicked lightning button in a table (in an aura:iteration) change from neutral to success once clicked.

Below is the component:

<aura:component description="ResourceTiles" implements="forceCommunity:searchInterface" controller="MainBrowser">

<aura:attribute name="resources" type="Resource__c[]" access="public" />

<aura:attribute name="selectedResourceId" type="Id" access="public" />


<aura:attribute name="currentColor" type="String" default="neutral" />
<aura:attribute name="currentImage" type="String" default="utility:add" />


<aura:registerEvent name="ResourceSelected" type="c:ResourceSelected" />



<div class="slds-scrollable--x">
    <table class="slds-table slds-table--bordered slds-table--cell-buffer slds-table--striped">
    <thead>
        <tr class="slds-text-title_caps">
            <th scope="col"><div class="slds-truncate" title="Car Selection"></div></th>
            <th scope="col"><div class="slds-truncate" title="Model">Car Model</div></th>
            <th scope="col"><div class="slds-truncate" title="Engine Information">Engine</div></th>

        </tr>
        </thead>
        <tbody>
        <aura:iteration items="{!v.resources}" var="resource">
            <tr>
                <td>
                    <lightning:button variant="{!v.currentColor}" iconName="{!v.currentImage}" value="{!resource.Id}"
                                      aura:id="allButtons" onclick="{!c.changeColor}" />
                </td>
                <td>
                    <div class="slds-truncate" title="{!resource.Name}">
                        {!resource.Name}
                    </div>
                </td>
                <td>
                    <div class="slds-truncate" title="{!resource.Comment__c}">
                        {!resource.Comment__c}
                    </div>
                </td>
            </tr>
        </aura:iteration>
        </tbody>
    </table>
</div>

and below is the controller:

 changeColor: function(component, event, helper) { 



    var allButtons = component.find("allButtons"); 
    if ($A.util.isArray(allButtons)) {
        allButtons.forEach(button => {
            button.set("v.currentColor", "neutral")
            button.set("v.currentImage", "utility:add")
        })
    }


    var currentButton = event.getSource(); 
    currentButton.set("v.currentColor", "success");
    currentButton.set("v.currentImage", "utility:check");
},

My question is, where is my logic flawed? I want the currently clicked button to change from "neutral" in variant and "utility:add" in iconName to "success" and "utility:check" once clicked.

Appreciate your help!

Best Answer

Based on the lightning:button documentation these are the attribute names to set:

currentButton.set("v.variant", "success");
currentButton.set("v.iconName", "utility:check");

Assuming you don't want all the buttons set to the same thing, probably best not to bind all the buttons to one pair of attributes so maybe use:

<lightning:button
        variant="{#v.initialColor}"
        iconName="{#v.initalImage}"
        value="{!resource.Id}"
        aura:id="allButtons"
        onclick="{!c.changeColor}"
        />

PS

Related to the comment about the visibility of the attributes, one approach is to create your own wrapper component (so that it is in your namespace and so access to its attributes are not blocked by the LockerService).

PPS

The wrapper would be (with the changeColor function moved too):

<aura:component>

    <aura:attribute name="variant" type="String"/>
    <aura:attribute name="iconName" type="String"/>
    <aura:attribute name="resourceId" type="Id"/>

    <lightning:button
            variant="{!v.variant}"
            iconName="{!v.iconName}"
            value="{!v.resourceId}"
            onclick="{!c.changeColor}"
            />

</aura:component>

referenced in your existing component like this:

<td>
    <c:button
            aura:id="allButtons"
            variant="{#v.currentColor}"
            iconName="{#v.currentImage}"
            resourceId="{#v.resourceId}"
            />
</td>
Related Topic