0

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!

1

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>
12
  • I tried that too without any success, getting error saying: Access Check Failed! AttributeSet.set(): 'variant' of component 'markup://c:ResourceTiles {958:0}' is not visible to 'markup://c:ResourceTiles {958:0}'. – erikvm Apr 29 '18 at 17:36
  • 1
    @erikvm The dreaded LockerService presumably... If it is that see the PS. – Keith C Apr 29 '18 at 17:42
  • How would I go about doing that? Also, your suggestion with the "variant="{#v.initialColor}" - isn't that exactly what I'm doing right now? I'm not seeing any difference – erikvm Apr 29 '18 at 17:56
  • @erikvm On the {# difference to {! see e.g. salesforce.stackexchange.com/questions/138348/…. The wrapper deal is to just add the same attributes to your component and pass them into the lightning:button. – Keith C Apr 29 '18 at 19:45
  • Can you please elaborate on the wrapper deal? What specifically should I add as attributes? Because from my original post - isn't that what I have done? <aura:attribute name="currentColor" type="String" default="neutral" /> <aura:attribute name="currentImage" type="String" default="utility:add" /> And then in the lightning:button <lightning:button variant="{!v.currentColor}" iconName="{!v.currentImage}" – erikvm Apr 29 '18 at 20:49
1

I found a workaround solution to it.

markup:

<aura:component description="ResourceTiles">
<aura:attribute name="selectedResourceId" type="Id" access="public" />
<aura:registerEvent name="ResourceSelected" type="c:ResourceSelected" />

<aura:attribute name="resources" type="Object"/>
<aura:attribute name="mycolumns" type="List"/>
<aura:handler name="init" value="{! this }" action="{! c.doInit }"/>
<lightning:datatable aura:id="lightningTable"
                     data="{! v.resources }"
                     columns="{! v.mycolumns }"
                     keyField="Id"
                     onrowaction="{! c.handleRowAction }"
                     hideCheckboxColumn="true"
/>

controller:

doInit: function(component, event, helper) {
    component.set('v.mycolumns', [
        {type: "button", typeAttributes: {
            label: '',
            iconName: 'utility:add',
            name: 'selectRecord',
            title: 'selectRecord',
            disabled: false,
            value: 'edit',
            variant: {fieldName: 'variantValue'},
        }},



handleRowAction: function(component, event, helper) {
    var resource = event.getParam("row")
    var action = event.getParam("action");
    if (action.name == "selectRecord") {
        var event = component.getEvent("ResourceSelected");
         event.setParams({
                resourceId: resource.Id, // 
        });
    }
 event.fire();
 helper.addRow(component, resource);

},

and the helper:

addRow: function (component, row) {
        var data = component.get('v.resources');
        data = data.map(function(rowData) {
            if (rowData.Id === row.Id) {
                rowData.variantValue = 'Success';

            }
            else {
                rowData.variantValue = "Neutral";
            }
            return rowData;
        });
        component.set("v.resources", data);
 }
3
  • Can you also add the component markup to the answer? – Keith C Apr 30 '18 at 19:23
  • Sure, added the markup. – erikvm Apr 30 '18 at 20:02
  • Thanks - answer is clearer explicitly showing thelightning:datatable. – Keith C Apr 30 '18 at 20:11

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.