4

I have designed an Account and its Contacts relationship in lightning Collapsible and Accordion style. The data populating correctly but since it is under aura:iteration, everytime it is getting the same Id for expand and collapse.

This is Account names without expanding enter image description here

Now, when I click on single account to see the contacts, it is expanding all the accounts. enter image description here

Component:

<aura:component controller="collapseSecController">
    <aura:attribute name="accounts" type="Account[]"/>
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />

    <div class="slds-p-around--large">
        <aura:iteration items="{!v.accounts}" var="acc">
            <div class="slds-page-header" style="cursor: pointer;" onclick="{!c.sectionOne}">
                <section class="slds-clearfix">
                    <div class="slds-float--left ">
                        <lightning:icon class="slds-show" aura:id="articleOne" iconName="utility:add" size="x-small" alternativeText="Indicates add"/>
                        <lightning:icon class="slds-hide" aura:id="articleOne" iconName="utility:dash" size="x-small" alternativeText="Indicates dash"/>
                    </div>
                    <div class="slds-m-left--large">{!acc.Name}</div>
                </section>
            </div>
            <div class="slds-hide slds-p-around--medium" aura:id="articleOne">
                <table class="slds-table slds-table--bordered slds-table--cell-buffer slds-table--striped slds-max-medium-table--stacked-horizontal"
                       role="grid">
                    <thead>
                        <tr>
                            <th class="slds-is-sortable slds-cell-wrap" scope="col">
                                Header Code
                            </th>
                           <th class="slds-is-sortable slds-cell-wrap" scope="col">
                                Account Name
                            </th>
                            <th class="slds-is-sortable slds-cell-wrap" scope="col">
                                Product Name
                            </th>
                            <th class="slds-is-sortable slds-cell-wrap" scope="col">
                                Manufacturer
                            </th>
                            <th class="slds-is-sortable slds-cell-wrap" scope="col">
                                Asset Code
                            </th>
                            <th class="slds-is-sortable slds-cell-wrap" scope="col">
                                Serial Number
                            </th>
                        </tr>
                    </thead>
                    <tbody>
                        <aura:iteration items="{!acc.Contacts}" var="con">

                           <tr class="slds-hint-parent">
                                <td role="gridcell" class="slds-cell-wrap" data-label="Name">
                                    {!acc.Name}
                                </td>
                                <td role="gridcell" class="slds-cell-wrap" data-label="accName">
                                    {!con.AccountName__c}
                                </td>
                                <td role="gridcell" class="slds-cell-wrap" data-label="prName">
                                    {!con.ProductName__c}
                                </td>
                                <td role="gridcell" class="slds-cell-wrap" data-label="manuName">
                                    {!acc.Manufacturer__c}
                                </td>   
                                <td role="gridcell" class="slds-cell-wrap" data-label="manuName">
                                    {!con.HdrName__c}
                                </td> 
                                <td role="gridcell" class="slds-cell-wrap" data-label="manuName">
                                    {!con.Mfrserialnumber__c}
                                </td> 

                            </tr>

                        </aura:iteration>
                    </tbody>
                </table>
            </div>
        </aura:iteration>      

    </div>
</aura:component>

Controller.js

({
    doInit : function(component, event, helper) {
        helper.getAccountAndContactsRelation(component);
    },

    sectionOne : function(component, event, helper) {
       helper.helperFun(component,event,'articleOne');
    }
})

Helper.js

 ({
        getAccountAndContactsRelation : function(cmp) {
            var action = cmp.get("c.getAccountAndContactsRelation");
            action.setCallback(this, function(response){
                var state = response.getState();
                if (state === "SUCCESS") {
                    cmp.set("v.accounts", response.getReturnValue());


         }
        });
        $A.enqueueAction(action);
    },
    helperFun : function(component,event,secId) {
      var acc = component.find(secId);
            for(var cmp in acc) {
            $A.util.toggleClass(acc[cmp], 'slds-show');  
            $A.util.toggleClass(acc[cmp], 'slds-hide');  
       }
    },
})

4 Answers 4

5

Try using lightning:accordion and lightning:accordionSection components which is very simpler for handling.

Reference: lightning:accordion

Check this out:

Component:

<aura:component controller="AccountsController">
<aura:attribute name="accounts" type="Account[]"/>
<aura:handler name="init" value="{!this}" action="{!c.doInit}" />

<lightning:accordion activeSectionName="B">
    <aura:iteration items="{!v.accounts}" var="acc" indexVar="ind">
        <lightning:accordionSection name="{!ind}" label="{!acc.Name}">
            {!acc.Name} - {!acc.Phone}
             //Add your table & data here
        </lightning:accordionSection>
    </aura:iteration>
</lightning:accordion>        

Controller:

doInit : function(component, event, helper) {
    helper.getAccountAndContactsRelation(component);
}

Helper:

 getAccountAndContactsRelation : function(cmp) {
    var action = cmp.get("c.getAcc");
    action.setCallback(this, function(response){
        var state = response.getState();
        if (state === "SUCCESS") {
            console.log('response.getReturnValue()',response.getReturnValue());
            cmp.set("v.accounts", response.getReturnValue());


        }
    });
    $A.enqueueAction(action);
}

Class:

public class AccountsController {

    @AuraEnabled
    public static List<Account> getAcc(){
        return [SELECT id,name,Phone FROM Account LIMIT 4];
    }
}

Hope this helps.

3
  • This will give the same ui of what I posted? Jan 5, 2018 at 10:26
  • 1
    Yes, This will give you a neat and organised ui. And more responsive to all devices. You may refer lightning design System -lightningdesignsystem.com And you can handle actions more easily. Has a collection of attributes that can be passed for user's need. Can also be customised.
    – A.Bretto
    Jan 5, 2018 at 10:29
  • @mohammedazarudeen you should use this in build component. Jan 5, 2018 at 12:15
1

You will have to tweak the code so that only for the current target element the toggle is active while for rest it is inactive .

helperFun : function(component,event,secId) {
  var acc = component.find(secId);
  acc.forEach(function(element) {
        $A.util.toggleClass(element, "slds-hide");
    });
    $A.util.addClass(event.target, "slds-show");
}

Alternatively create a separate child component to represent your section and then component.find will have only instance and rest of them are segregated .

Create a component called collapisbleSection like below

<aura:component >
  <aura:attribute name="acc" type="Account"/>
   <div class="slds-page-header" style="cursor: pointer;" onclick="{!c.sectionOne}">
            <section class="slds-clearfix">
                <div class="slds-float--left ">
                    <lightning:icon class="slds-show" aura:id="articleOne" iconName="utility:add" size="x-small" alternativeText="Indicates add"/>
                    <lightning:icon class="slds-hide" aura:id="articleOne" iconName="utility:dash" size="x-small" alternativeText="Indicates dash"/>
                </div>
                <div class="slds-m-left--large">{!v.acc.Name}</div>
            </section>
        </div>
        <div class="slds-hide slds-p-around--medium" aura:id="articleOne">
            <table class="slds-table slds-table--bordered slds-table--cell-buffer slds-table--striped slds-max-medium-table--stacked-horizontal"
                   role="grid">
                <thead>
                    <tr>
                        <th class="slds-is-sortable slds-cell-wrap" scope="col">
                            Header Code
                        </th>
                       <th class="slds-is-sortable slds-cell-wrap" scope="col">
                            Account Name
                        </th>
                        <th class="slds-is-sortable slds-cell-wrap" scope="col">
                            Product Name
                        </th>
                        <th class="slds-is-sortable slds-cell-wrap" scope="col">
                            Manufacturer
                        </th>
                        <th class="slds-is-sortable slds-cell-wrap" scope="col">
                            Asset Code
                        </th>
                        <th class="slds-is-sortable slds-cell-wrap" scope="col">
                            Serial Number
                        </th>
                    </tr>
                </thead>
                <tbody>
                    <aura:iteration items="{!v.acc.Contacts}" var="con">

                       <tr class="slds-hint-parent">
                            <td role="gridcell" class="slds-cell-wrap" data-label="Name">
                                {!v.acc.Name}
                            </td>
                            <td role="gridcell" class="slds-cell-wrap" data-label="accName">
                                {!con.AccountName__c}
                            </td>
                            <td role="gridcell" class="slds-cell-wrap" data-label="prName">
                                {!con.ProductName__c}
                            </td>
                            <td role="gridcell" class="slds-cell-wrap" data-label="manuName">
                                {!v.acc.Manufacturer__c}
                            </td>   
                            <td role="gridcell" class="slds-cell-wrap" data-label="manuName">
                                {!con.HdrName__c}
                            </td> 
                            <td role="gridcell" class="slds-cell-wrap" data-label="manuName">
                                {!con.Mfrserialnumber__c}
                            </td> 

                        </tr>

                    </aura:iteration>
                </tbody>
            </table>
        </div>
     <aura:component >

The controller will be as below

({
  sectionOne : function(component, event, helper) {
     var acc = component.find('articleOne');
     $A.util.toggleClass(acc, 'slds-show');  
  }
})

Now the parent component will be modified as below

<aura:component controller="collapseSecController">
  <aura:attribute name="accounts" type="Account[]"/>
  <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
    <div class="slds-p-around--large">
      <aura:iteration items="{!v.accounts}" var="acc">
        <c:collapisbleSection acc="{!acc}"/>
      </aura:iteration>
     </div>
  </aura:component>

Also if your styling needs are one matching the lightning design system , use the latest lightning:accordian tag

4
  • I have tried the same helperFun but no luck. Jan 5, 2018 at 10:12
  • Getting error for the above alternative method Assertion Failed!: Unable to get value for key 'acc.Contacts'. No value provider was found for 'acc'. : false Callback failed: apex://collapseSecController/ACTION$getAccountAndContactsRelation Jan 5, 2018 at 10:20
  • Looks like I missed to use v dot .check the updated code . Jan 5, 2018 at 12:09
  • Can we also add collapse all and expand all with this example. I tried but, couldn't get rid of it. @MohithShrivastava
    – Vickal
    Apr 27, 2018 at 10:25
0

allowMultipleSectionsOpen="false" or true, set this in accordionsection and it will work

-1

Above solution works with minor changes. Please refer below.

//Parent Component

<aura:component controller="collapseSecController">
    <aura:attribute name="accounts" type="Account[]"/>
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
    <div class="slds-p-around--large">
      <aura:iteration items="{!v.accounts}" var="acc">
        <c:collapisbleSection acc="{!acc}"/>
      </aura:iteration>
     </div>
    </aura:component>

//Parent cmp controller

({
    doInit : function(cmp) {
        var action = cmp.get("c.getAcc");
        action.setCallback(this, function(response){
            var state = response.getState();
            if (state === "SUCCESS") {
                console.log('response.getReturnValue()',response.getReturnValue());
                cmp.set("v.accounts", response.getReturnValue());
            }
        });
        $A.enqueueAction(action);
    }
})

//Collapsible Child Component

<aura:component >
  <aura:attribute name="acc" type="Account"/>
   <div class="slds-page-header" style="cursor: pointer;" onclick="{!c.sectionOne}">
            <section class="slds-clearfix">
                <div class="slds-float--left ">
                    <lightning:icon class="slds-show" aura:id="articleOne" iconName="utility:add" size="x-small" alternativeText="Indicates add"/>
                    <lightning:icon class="slds-hide" aura:id="articleOne" iconName="utility:dash" size="x-small" alternativeText="Indicates dash"/>
                </div>
                <div class="slds-m-left--large">{!v.acc.Name}</div>
            </section>
        </div>
        <div class="slds-hide slds-p-around--medium" aura:id="articleOne">
            <table class="slds-table slds-table--bordered slds-table--cell-buffer slds-table--striped slds-max-medium-table--stacked-horizontal"
                   role="grid">
                <thead>
                    <tr>
                        <th class="slds-is-sortable slds-cell-wrap" scope="col">
                            Header Code
                        </th>
                       <th class="slds-is-sortable slds-cell-wrap" scope="col">
                            Account Name
                        </th>
                        <th class="slds-is-sortable slds-cell-wrap" scope="col">
                            Product Name
                        </th>
                        <th class="slds-is-sortable slds-cell-wrap" scope="col">
                            Manufacturer
                        </th>
                        <th class="slds-is-sortable slds-cell-wrap" scope="col">
                            Asset Code
                        </th>
                        <th class="slds-is-sortable slds-cell-wrap" scope="col">
                            Serial Number
                        </th>
                    </tr>
                </thead>
                <tbody>
                    <aura:iteration items="{!v.acc.Contacts}" var="con">

                       <tr class="slds-hint-parent">
                            <td role="gridcell" class="slds-cell-wrap" data-label="Name">
                                {!v.acc.Name}
                            </td>
                            <td role="gridcell" class="slds-cell-wrap" data-label="accName">
                                {!con.AccountName__c}
                            </td>
                            <td role="gridcell" class="slds-cell-wrap" data-label="prName">
                                {!con.ProductName__c}
                            </td>
                            <td role="gridcell" class="slds-cell-wrap" data-label="manuName">
                                {!v.acc.Manufacturer__c}
                            </td>   
                            <td role="gridcell" class="slds-cell-wrap" data-label="manuName">
                                {!con.HdrName__c}
                            </td> 
                            <td role="gridcell" class="slds-cell-wrap" data-label="manuName">
                                {!con.Mfrserialnumber__c}
                            </td> 

                        </tr>

                    </aura:iteration>
                </tbody>
            </table>
        </div>
     <aura:component >

//Collapsible child Controller

({
    sectionOne : function(component, event, helper) {
        var acc = component.find('articleOne');
        acc.forEach(function(element) {
            $A.util.toggleClass(element, "slds-hide");
        });
        $A.util.addClass(event.target, "slds-show");
    },
    
    
})
4
  • 1
    This answer is a code dump. It doesn't explain what the differences are, or why those differences matter. The explanation is as important as the rest of the answer.
    – Derek F
    Mar 3 at 12:16
  • Please check the child javascript controller and you will get the difference. Anyone can easily go through the above code and figure out the differences. There is no need of further explanation. If you have any concerns, try the code in any console and see the result.
    – Ashams
    Mar 4 at 13:04
  • The onus is on you to explain what the difference is.
    – Derek F
    Mar 4 at 13:05
  • Sorry Derek, that can’t be my responsibility. Can’t spoon feed everything
    – Ashams
    Mar 4 at 13:08

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.