2

I am displaying a set of button group listed from 1 to 5, highlighting button 1 after my jQuery library has been loaded. Once the next button is clicked, i am changing the button group from 6 to 10, and would like to highlight button 8 which is not happening in my case.

Lightning Component

<aura:component >
    <ltng:require scripts="{!$Resource.jQueryLib + '/js/jquery-3.1.1.min.js'}" 
                  afterScriptsLoaded="{!c.afterScriptsLoaded}"/>
    <aura:attribute name="pageNumberList" type="List"/>

     <aura:handler name="init" value="{!this}" action="{!c.doInit}" />

     <div class="slds-button-group" role="group">    
        <aura:iteration items="{!v.pageNumberList}" var="pageNum">
           <button class="slds-button slds-button--neutral" 
                   id="{!pageNum.value}" 
                   onclick="{!c.offsetChanged}">
                   {!pageNum.value}
           </button>
        </aura:iteration>
            <button class="slds-button slds-button--neutral"            
                    onclick="{!c.nextPageClicked}">Next</button>
     </div>
</aura:component>

Controller

 doInit : function(component, event, helper)
    { 
        var numberList = [];
        for(var i=1;i<6;i++)
        {
            numberList.push({
                value:i
            });
        }
        component.set("v.pageNumberList", numberList);
    },
 afterScriptsLoaded:function(component, event, helper){
      jQuery("#1").removeClass("slds-button--neutral").addClass("slds-button--brand activeBlue"); 
    },
 nextPageClicked:function(component, event, helper)
    {
        var numberList = [];
        for(var i=6;i<11;i++)
        {
            numberList.push({
                value:i
            });
        }
        component.set("v.pageNumberList", numberList);

        //**This step is executing but not shown on the DOM**//
        jQuery("#8").removeClass("slds-button--neutral").addClass("slds-button--brand activeBlue");
        console.log(jQuery("#8").attr("class"));
    }

enter image description here

enter image description here

Interesting fact

console.log statement at the last line of code prints slds-button--brand activeBlue.

I understand that the component.set resetting my button group to its initial state, but why is my jQuery.removeClass() method executing but not rendering on the DOM?

  • Why use jQuery to do this? Lightning provides the ability to do this native: developer.salesforce.com/docs/atlas.en-us.lightning.meta/… – techbusinessman Feb 1 '17 at 20:41
  • Yeah, I've seen that. Unfortunately, in-order to use component.find, I have to use aura:id and aura:id doesn't support expressions (only string literals). Without expressions, i cannot give unique aura:id for each button under aura:iteration. – sam_s Feb 1 '17 at 20:54
  • 1
    I'd do one of two things then, dynamically create the components so you can dynamically add the aura:id or create a child component that contains everything in the iteration so you can use a static aura:id in the child component. – techbusinessman Feb 1 '17 at 20:57
4

You should be using the built in A api provided by Lightning.

To add or remove a class, call something like this:

var element = component.find('someAuraId');
$A.util.addClass(element, 'your-class');

However, I can see that you would need DYNAMIC ids for this, which means you can't use aura:id

There is another way though - use the source list to provide the styling.

In the init method, call this:

doInit : function(component, event, helper) { 
    var numberList = [{'value':1,'class':'slds-button--brand activeBlue'},
                      {'value':2,'class':'slds-button--neutral'},
                      {'value':3,'class':'slds-button--neutral'},
                      {'value':4,'class':'slds-button--neutral'},
                      {'value':5,'class':'slds-button--neutral'},
                      {'value':6,'class':'slds-button--neutral'}]
    component.set("v.pageNumberList", numberList);
},

Now remove the afterScriptsLoaded method, as it's all encapsulated in the init method.

In after this, your can just call a generic setter/unsetter for these classes:

addClassToButtons(component,index,clazz){
    var myList = component.get("v.pageNumberList");

    for(var i=0;i<myList.length;i++){
        var elem = numberList[i];
        if (elem.value == index){
          elem.class = clazz;
        }
        else {
          elem.class = "";
        }
    }
    component.set("v.pageNumberList",myList);
}

Then, in your iteration, just append the class to what is there:

<aura:iteration items="{!v.pageNumberList}" var="pageNum">
   <button class="{#pageNum.class + ' slds-button '}" 
       onclick="{!c.offsetChanged}">
          {#pageNum.value}
   </button>
</aura:iteration>
  • I thought this was an anti-pattern, won't doing the get/set cause a multiple items set performance issue? developer.salesforce.com/docs/atlas.en-us.lightning.meta/… – techbusinessman Feb 1 '17 at 21:06
  • It will cause the list to rerender. If you were worried about performance, just use one way binding – Caspar Harmer Feb 1 '17 at 21:08
  • 1
    I see you are talking about the init part - hmm good point. Still the main part of the answer is good - I will change my answer though, as I see his afterScripsLoaded method alters the list again - hadn't see that. – Caspar Harmer Feb 1 '17 at 21:16
  • @CasparHarmer The idea of getting the class attribute from list fixed my issue. Brilliant one, thanks. Although, out of curiosity why is that jQuery.removeClass() is not working there? Any idea? pardon my lack of understanding on any obvious concepts here. – sam_s Feb 1 '17 at 22:01
  • 1
    I'm not totally sure, to be honest. However, the Lightning Framework mediates all access to the dom, so at the most basic level, I'd say that JQuery is being blocked from accessing that item. The Framework takes all the HTML that you see replaces it - or wraps it (I am not sure on which) with it's own markup. Perhaps the fact that you were trying to modify DOM inside an aura:iteration meant that you were essentially in another component - and you can't modify the contents of another component. More: developer.salesforce.com/docs/atlas.en-us.lightning.meta/… – Caspar Harmer Feb 1 '17 at 22:09

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.