[SalesForce] Lightning – Show/hide section function div with same ids triggering at the same time when one div is clicked

When a div is clicked i want to show some information. I have two divs with the same ids referring the same function. I want the event to be triggered only when the corresponding div is clicked. It is not happening as expected. I understand here because divs refer the same id the function is triggered to other div's also even though it is not clicked. I am confused on how to overcome this. Can someone guide me how to resolve this?

Aura Component:

<aura:component >
    <aura:attribute name="collapseText" type="String" default="[+]"/>
    <div>
        <div class="Message">
            <div style="width:90%;float:left">Individual Information</div>
            <div class="expandCollapse" onclick="{!c.ToggleCollapse}">{!v.collapseText}</div>
        </div>
        <div class="container hide" aura:id="containerCollapsable">
           <p>Hello</p> 
        </div>
    </div>
    <div>
        <div class="Message">
            <div style="width:90%;float:left">Group Information</div>
            <div class="expandCollapse" onclick="{!c.ToggleCollapse}">{!v.collapseText}</div>
        </div>
        <div class="container hide" aura:id="containerCollapsable">
           <p>Hello</p> 
        </div>
    </div>
</aura:component>

Controller:

({
    ToggleCollapse : function(component, event, helper) { 
        helper.ToggleCollapseHandler(component, event);

    }
})

Helper

({
    ToggleCollapseHandler : function(component, event) { 
        var existingText = component.get("v.collapseText");
       var container = component.find("containerCollapsable") ;
        if(existingText === "[ - ]"){
             component.set("v.collapseText","[ + ]");
            $A.util.addClass(container, 'hide');
        }else{
            component.set("v.collapseText","[ - ]"); 
            $A.util.removeClass(container, 'hide'); 
        }  
    }
})

Best Answer

The problem is that each section is using the same information. For example, when you toggle one collapse area, the other's +/- sign will also toggle.

The easiest way to resolve this is to create a new component:

<aura:component>
<aura:attribute name="title" type="String" />
<aura:attribute name="collapseText" type="String" default="[+]"/>
<div>
    <div class="Message">
        <div style="width:90%;float:left">{!v.title}</div>
        <div class="expandCollapse" onclick="{!c.ToggleCollapse}">{!v.collapseText}</div>
    </div>
    <div class="container hide" aura:id="containerCollapsable">
       {!v.body}
    </div>
</div>
<aura:component>

From there, you can refactor your code:

<aura:component>
    <c:collapsibleSection title="Individual Information">
       <p>Hello</p> 
    </c:collapsibleSection>
    <c:collapsibleSection title="Group Information">
       <p>Hello</p> 
    </c:collapsibleSection>
</aura:component>

Otherwise, if you don't want a separate component, you'll have to add more code to your component:

<aura:component >
    <aura:attribute name="collapseText" type="String[]" default="['[ + ]','[ + ]']"/>
    <div>
        <div class="Message">
            <div style="width:90%;float:left">Individual Information</div>
            <div data-collapse-index="0" class="expandCollapse" onclick="{!c.ToggleCollapse}">{!v.collapseText[0]}</div>
        </div>
        <div class="container hide" aura:id="containerCollapsable">
           <p>Hello</p> 
        </div>
    </div>
    <div>
        <div class="Message">
            <div style="width:90%;float:left">Group Information</div>
            <div data-collapse-index="1" class="expandCollapse" onclick="{!c.ToggleCollapse}">{!v.collapseText[1]}</div>
        </div>
        <div class="container hide" aura:id="containerCollapsable">
           <p>Hello</p> 
        </div>
    </div>
</aura:component>

You can then determine which element to use based on the attribute value:

({
    ToggleCollapseHandler : function(component, event) { 
        var index = event.target.data.collapseIndex;
        var existingText = component.get("v.collapseText["+index+"]");
       var container = component.find("containerCollapsable")[index];
        if(existingText === "[ - ]"){
             component.set("v.collapseText["+index+"]","[ + ]");
            $A.util.addClass(container, 'hide');
        }else{
            component.set("v.collapseText["+index+"]","[ - ]"); 
            $A.util.removeClass(container, 'hide'); 
        }  
    }
})

It'd also be easier if you could reorganize your code so that the collapse section contained the element to collapse, because then you could toggle the parent class directly. You could further ease your troubles by displaying the + or - via CSS, which would eliminate the need for the text attribute, which could further simplify your code.

Here's an example:

<aura:component >
    <div class="collapse hide" aura:id="individualInfo">
        <div class="Message">
            <div style="width:90%;float:left">Individual Information</div>
            <div data-target="individualInfo" class="expandCollapse" onclick="{!c.ToggleCollapse}"></div>
        </div>
        <div class="container" aura:id="containerCollapsable">
           <p>Hello</p> 
        </div>
    </div>
    <div class="container hide" aura:id="groupInfo">
        <div class="Message">
            <div style="width:90%;float:left">Group Information</div>
            <div data-target="groupInfo" class="expandCollapse" onclick="{!c.ToggleCollapse}"></div>
        </div>
        <div class="container" aura:id="containerCollapsable">
           <p>Hello</p> 
        </div>
    </div>
</aura:component>

From there, you can then simply modify your CSS files as necessary:

.THIS .hide .container {
    display: none;
}
.THIS .expandCollapse::after {
    content: "[ - ]"
}
.THIS .hide .expandCollapse::after {
    content: "[ + ]"
}
Related Topic