Skip to main content
1 of 3
Omkar K
  • 63
  • 1
  • 8

AccordianSection name property is dynamically not changed, leading to serious problem in iteration

Hi I am working on a problem where I have multiple records of an Object to be shown and each of these records, will have many child records of It's Child Object.

I have chosen AccordianSection to show parent record and A Table to show Children of each.

Also, I need to provide New, Clone and Delete Functionality for each record. Also, an "Expand All | Collapse All" feature.

So, I am using aura:iteration to dynamically generate lightning:accordionSection. I have tried to assign a unique Name to each AccordianSection by using, Id/Name in conjunction with index of iteration, so that I can easily collect the names of AccordianSections while iterating through record list and could assign it to "activeSections" attribute, which will be used by lightning:accordian to expand listed AccordianSections.

But, My observation is, once AccordianSections are rendered, It's name doesn't change, when I Clone or Delete a Record, Even though AccordianSections are rendered properly. event.getParam("openSections") always gives old value.

Because of this Expand All | Collapse All functionality is not working.

Component markup

<aura:component controller="MBUCampaignTicketCtrl" implements="force:appHostable">
    <aura:attribute name="index" type="Integer" default="0"/>
    <aura:attribute name="parentId" type="String"/>
    <aura:attribute name="caseId" type="String"/>
    <aura:attribute name="campaigns" type="MBUCampaignTicketCtrl.CampaignWithLineItems[]"/>
    <aura:attribute name="activeSections" type="List" />
    <aura:attribute name="activeSectionsMessage" type="String" default="" />
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
    
    <p>{! v.activeSectionsMessage }</p><br/>
    <p><a onclick="{!c.handleExpandAll}">Expand All</a>&nbsp;|&nbsp;<a onclick="{!c.handleCollapseAll}">Collapse All </a></p>
    <lightning:accordion allowMultipleSectionsOpen="true"
                         onsectiontoggle="{! c.handleSectionToggle }"
                         activeSectionName="{! v.activeSections }"
                         >
        
        <aura:iteration items="{!v.campaigns}" var="campaignWrp" indexVar="index">
            <lightning:accordionSection aura:id="accor" name="{!(index+1)+''}"
                                        label="{!(index+1)+'. '+campaignWrp.campaign.Name}">
                <br/>
                <!--form class="slds-form-stacked"-->
                <div class="slds-grid slds-gutters slds-wrap slds-grid_align-space">
                    <div class="slds-col slds-align_absolute-center form-group">
                         <!--onclick="{!c.goToStoreDetail}"-->
                        <span>
                            <lightning:input aura:id="CampaignName" label="Campaign Name"
                                             name="CampaignName" value="{!campaignWrp.campaign.Name}" />
                            
                    <div class="slds-col slds-align_absolute-center form-group">
                        <span>
                            <lightning:button value="{!index}" label="New" onclick="{!c.appendNewCampaign}" 
                                              class="slds-button_brand"/>
                            <lightning:button value="{!index}" label="Clone" onclick="{!c.cloneCampaign}" 
                                              class="slds-button_brand"/>
                            <lightning:button value="{!index}" label="Delete" onclick="{!c.deleteCampaign}" 
                                              class="slds-button_neutral" disabled="{!v.campaigns.length == 1}"/>
                        </span>
                    </div>
                </div>
                <!--/form-->
                <br/>
            </lightning:accordionSection>
        </aura:iteration>
    </lightning:accordion>
    
</aura:component>

JS Controller

({
    doInit : function(component, event, helper){
        var campaigns = component.get("v.campaigns");
        console.log(component.get("v.caseId"));
        if(typeof(campaigns) !== "undefined" && !$A.util.isEmpty(campaigns)){
            campaigns[0].campaign.Id = '';
            campaigns[0].campaign.Name = "New Campaign";
            component.set("v.campaigns", campaigns);
            
            component.set("v.activeSections", "1");
            console.log(component.get("v.activeSections"));
        }
        console.log(campaigns[0].campaign);
    },
    
    appendNewCampaign : function(component, event, helper){
        helper.appendNewCampaign(component, event, helper);
    },
    
    cloneCampaign : function(component, event, helper){
        helper.cloneCampaign(component, event, helper);
    },
    
    deleteCampaign : function(component, event, helper){
        helper.deleteCampaign(component, event, helper);
    },
    
    
    handleExpandAll : function(component, event, helper){
        var activeSections = component.get("v.activeSections");
        activeSections = [];
        var campaigns = component.get("v.campaigns");
        if(typeof(campaigns) == "object"){
            for(var i in campaigns){
                activeSections.push((parseInt(i)+1).toString());
            }
        }
        component.set("v.activeSections", openSections);
    },
    
    handleCollapseAll : function(component, event, helper){
        var activeSections = component.get("v.activeSections");
        console.log(activeSections);
        activeSections = [];
        
        component.set("v.activeSections", activeSections);
    },
    
    handleSectionToggle : function(component, event, helper){
        var openSections = event.getParam("openSections");
        console.log(openSections);
        if(openSections.length === 0){
            component.set("v.activeSectionsMessage", "All sections are closed");
        }else{
            component.set("v.activeSectionsMessage", "Open sections: " + openSections.join(', '));
        }
    }
})
JS Helper


({
    cloneObjectDeep : function (obj) {
        var clone = {};
        for(var i in obj) {
            if(obj[i] != null &&  typeof(obj[i])=="object"){
                clone[i] = this.cloneObjectDeep(obj[i]);
            }
            else{
                clone[i] = obj[i];
            }
        }
        console.log(clone);
        return clone;
    },
    appendNewCampaign : function(component, event, helper){
        var index = event.getSource().get("v.value");
        var campaigns = component.get("v.campaigns");
        var newElement = this.cloneObjectSh(campaigns[index]);
        newElement.campaign = {};
        newElement.caseCampaignLineItems = [{}];
        newElement.campaign.Id = '';
        newElement.campaign.Name = "New Campaign "+(index+1);
        campaigns.splice(index+1, 0, newElement);
        component.set("v.campaigns", campaigns);
        var indx = parseInt(index)+2;
        var activeSections = component.get("v.activeSections");
        activeSections.push(indx.toString());
        component.set("v.activeSections", activeSections);
        console.log(activeSections);
    },
    cloneCampaign : function(component, event, helper){
        var index = event.getSource().get("v.value");
        var campaigns = component.get("v.campaigns");
        var cloneElement = this.cloneObjectDeep(campaigns[index]);
        cloneElement.campaign.Id = '';
        campaigns.splice(index+1, 0, cloneElement);
        component.set("v.campaigns",campaigns);
        
        var indx = parseInt(index)+2;
        var activeSections = component.get("v.activeSections");
        activeSections.push(indx.toString());
        component.set("v.activeSections",activeSections);
        console.log(activeSections);
    },
    deleteCampaign : function(component, event, helper){
        var response = confirm("This Record will be deleted permanently. Do you Really want to Proceed?");
        if(response){
            var index = event.getSource().get("v.value");
            var campaigns = component.get("v.campaigns");
            console.log(index);
            var deleteElement = campaigns[index];
            if(deleteElement.Id == null){
                //campaigns.pop(deleteElement);
                campaigns.splice(index, 1);
                component.set("v.campaigns",campaigns);
            }else{
                
            }
        }else{
            return;
        }
    }
})
Apex Controller Wrapper


public class CampaignWithLineItems{
        @AuraEnabled
        public Case_Campaign__c campaign {get;set;}
        @AuraEnabled
        public List<Case_Campaign_Line_Item__c> caseCampaignLineItems {get;set;}
        @AuraEnabled
        public String campaignFlag {get;set;}

        public CampaignWithLineItems(Case_Campaign__c campaign, List<Case_Campaign_Line_Item__c> caseCampaignLineItems, String campaignFlag){
                this.campaign = campaign;
                this.caseCampaignLineItems = caseCampaignLineItems;
                this.campaignFlag = campaignFlag;
        }
        public CampaignWithLineItems(){
            this.campaign = new Case_Campaign__c();
            this.caseCampaignLineItems = new List<Case_Campaign_Line_Item__c>{new Case_Campaign_Line_Item__c()};
            this.campaignFlag = '';
        }
    }

Only solution I got till now is to always append new or cloned records at the end of the existing List of parent records, but I don't want to restrict users like this.

Omkar K
  • 63
  • 1
  • 8