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="CampaignCtrl" implements="force:appHostable">
<aura:attribute name="campaigns" type="CampaignCtrl.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> | <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/>
<div class="slds-grid slds-gutters slds-wrap slds-grid_align-space">
<div class="slds-col slds-align_absolute-center form-group">
<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>
<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.campaignLineItems = [{}];
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 Campaign__c campaign {get;set;}
@AuraEnabled
public List<Campaign_Line_Item__c> campaignLineItems {get;set;}
@AuraEnabled
public String campaignFlag {get;set;}
public CampaignWithLineItems(Campaign__c campaign, List<Campaign_Line_Item__c> campaignLineItems, String campaignFlag){
this.campaign = campaign;
this.campaignLineItems = campaignLineItems;
this.campaignFlag = campaignFlag;
}
public CampaignWithLineItems(){
this.campaign = new Campaign__c();
this.campaignLineItems = new List<Campaign_Line_Item__c>{new 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.