6

I am trying to do something that sounds easy in JavaScript but that I have difficulty to do with Lightning component.

The functionality is to highlight the currently pressed button as explained in this link.

I have created a div in my component as below :

<div id="myDIV">
  <lightning:button class="btn" aura:id="bout" label="1"/>
  <lightning:button class="btn active" aura:id="bout" label="2"/>
  <lightning:button class="btn" aura:id="bout" label="3"/>
  <lightning:button class="btn" aura:id="bout" label="4"/>
</div>

And the related css:

/* Style the buttons */
.THIS .btn {
  border: none;
  outline: none;
  padding: 10px 16px;
  background-color: #f1f1f1;
  cursor: pointer;
}

/* Style the active class (and buttons on mouse-over) */
.THIS .active{
  background-color: #666;
  color: white;
}

.THIS .btn:hover{
  background-color: #666;
  color: white;
}

And then try to add the listener to my helper :

addListeners: function (component){
        var header = document.getElementById("myDIV");
        var btns = header.getElementsByClassName("btn");
        for (var i = 0; i < btns.length; i++) {
            btns[i].addEventListener("click", function() {
                var current = document.getElementsByClassName("active");
                current[0].className = current[0].className.replace(" active", "");
                this.className += " active";
            });
        };
    }

And to finish create my render:

afterRender: function (component, helper) {
    var afterRend = this.superAfterRender();
    helper.addListeners(component)
    return afterRend;
}

The result look like this: enter image description here

However, when I click on another number, it doesn't update the DOM to define the clicked one as active.

Anyone to guide on how to succeed this?

2 Answers 2

4

I would not use afterRender to attach events, as you'll end up possibly adding duplicate events. Here's a simplified version that does not rely on a renderer:

<aura:application >
    <div id="myDIV" onclick="{!c.setActive}">
        <lightning:button class="btn" aura:id="bout" label="1"/>
        <lightning:button class="btn active" aura:id="bout" label="2"/>
        <lightning:button class="btn" aura:id="bout" label="3"/>
        <lightning:button class="btn" aura:id="bout" label="4"/>
    </div>
</aura:application>

({
    setActive: function(component, event, helper) {
        var bout = component.find("bout");
        bout.forEach(function(v) {
            $A.util.removeClass(v, "active");
        });
        $A.util.addClass(event.target, "active");
    }
})

Of course, in a real application, you'd probably put this method in a helper, but for demonstration purposes, the logic is instead in the controller.

2
  • You can create a component for button and iterate it incase the number of clickable buttons vary and use index to set the actively clicked button component.
    – RedDevil
    Commented Jan 4, 2018 at 17:29
  • 1
    @sfdcfox It works thanks! Only issue with this code is that if I click the div instead of a button it set the div as active.
    – Dimitri B
    Commented Jan 10, 2018 at 13:24
3

Since you have an aura:id on your button(s), why not simply use the toggle utility method to remove/add the class you need to highlight the button being pressed "onclick"? Javascript in the context of the aura:framework and with locker service will require a change of habits when developing.

since you have an aura:id set to "bout" for all your buttons, when you use component.find('bout'), it will return an array of elements, you should be able to easily remove the class from the current element and add it to the pressed button.

You must log in to answer this question.

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