Skip to content

Instantly share code, notes, and snippets.

@swapnilshrikhande
Last active March 1, 2021 07:30
Show Gist options
  • Save swapnilshrikhande/1f567827702970574069b2f52764c38f to your computer and use it in GitHub Desktop.
Save swapnilshrikhande/1f567827702970574069b2f52764c38f to your computer and use it in GitHub Desktop.
Dynamic record editor
<aura:component implements="flexipage:availableForAllPageTypes" access="global" controller="LightningRecordEditFormController">
<aura:attribute name="disabled" type="Boolean" default="false" />
<aura:attribute name="layoutSections" type="List" />
<aura:attribute name="saved" type="Boolean" default="false" />
<aura:attribute name="showSpinner" type="Boolean" default="true" />
<aura:attribute name="fieldName" type="String" default="StageName" />
<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
<lightning:card title="">
<aura:if isTrue="{!v.showSpinner}">
<lightning:spinner />
</aura:if>
<aura:if isTrue="{!!v.saved}">
<lightning:recordEditForm
onload="{!c.handleLoad}"
onsubmit="{!c.handleSubmit}"
onsuccess="{!c.handleSuccess}"
objectApiName="Contact">
<!-- the messages component is for error messages -->
<lightning:messages />
<aura:iteration items="{!v.layoutSections}" var="section">
<div class="slds-section slds-is-open">
<h3 class="slds-section__title">
{!section.label}
</h3>
<div class="slds-section__content">
<lightning:layout multipleRows="{!section.totalColumns > 1 }">
<aura:iteration items="{!section.lstFields}" var="field">
<lightning:layoutItem size="{! 12/section.totalColumns }" flexibility="auto" padding="around-small">
<aura:if isTrue="{!(!field.isReadOnly)}">
<lightning:inputField fieldName="{!field.fieldName}" />
<aura:set attribute="else">
<lightning:outputField fieldName="{!field.fieldName}" />
</aura:set>
</aura:if>
</lightning:layoutItem>
</aura:iteration>
</lightning:layout>
</div>
</div>
</aura:iteration>
<lightning:layout verticalAlign="center" class="x-large">
<lightning:layoutItem padding="around-large">
<div class="slds-m-top_medium">
<lightning:button disabled="{!v.disabled}" variant="brand" type="submit" name="save" label="Save" />
</div>
</lightning:layoutItem>
</lightning:layout>
</lightning:recordEditForm>
<aura:set attribute="else">
<p>Saved!</p>
</aura:set>
</aura:if>
</lightning:card>
</aura:component>
public class RecordForm {
public class RecordFormOptions {
@AuraEnabled
public String pageLayout;
}
@AuraEnabled
public static String getPageLayoutFields(String options) {
List<LayoutSection> lstSections = new List<LayoutSection>();
RecordFormOptions editorOptions = (RecordFormOptions) JSON.deserialize(options, RecordFormOptions.class);
try {
// Provide the page layout name here
// You can give multiple page layout names here as well
List<String> componentNameList = new List<String>{editorOptions.pageLayout};
// Retrieve page layout details
List<Metadata.Metadata> components = Metadata.Operations.retrieve(Metadata.MetadataType.Layout, componentNameList);
Metadata.Layout contLayout = (Metadata.Layout) components.get(0);
// We are going to find the fields names and will keep them according to columns so
// we can show them as per page layout
for( Metadata.LayoutSection ls : contLayout.layoutSections ) {
LayoutSection section = new LayoutSection( ls.label, ls.layoutColumns.size() );
List<LayoutColumn> lstColumns = new List<LayoutColumn>();
Integer maxFieldsInColumn = 0;
for( Metadata.LayoutColumn lc : ls.layoutColumns ) {
LayoutColumn column = new LayoutColumn();
// check if there are fields available in that column
if( lc.layoutItems != null ) {
// Get the max number of fields in a column to preserve the alignment
if( maxFieldsInColumn < lc.layoutItems.size() ) {
maxFieldsInColumn = lc.layoutItems.size();
}
for( Metadata.LayoutItem li : lc.layoutItems ) {
// Pass the LayoutItem object in the LayoutField consturctor
column.lstFields.add( new LayoutField( li ) );
}
}
// No need to add a column in the section if there is no field available
if( column.lstFields.size() > 0 ) {
lstColumns.add( column );
}
}
// Now, we need to arrange the fields in section so we can use them in the iteration
// on the component so we will have to arrange them in the order
if( maxFieldsInColumn > 0 ) {
for( Integer i = 0; i < maxFieldsInColumn; i++ ) {
for( Integer j = 0; j < lstColumns.size(); j++ ){
if( lstColumns[j].lstFields.size() > i ) {
section.lstFields.add( lstColumns[j].lstFields[i] );
}
else {
section.lstFields.add( new LayoutField() );
}
}
}
}
lstSections.add( section );
}
}
catch( Exception e ){
System.assert(false, e.getLineNumber() + ' : ' + e.getMessage() );
}
return JSON.serialize( lstSections );
}
public class LayoutSection {
@AuraEnabled public String label;
@AuraEnabled public List<LayoutField> lstFields;
@AuraEnabled public Integer totalColumns;
public LayoutSection( String label, Integer totalColumns ) {
this.label = label;
this.totalColumns = totalColumns;
this.lstFields = new List<LayoutField>();
}
}
private class LayoutColumn {
private List<LayoutField> lstFields;
public LayoutColumn() {
this.lstFields = new List<LayoutField>();
}
}
public class LayoutField {
@AuraEnabled public String fieldName;
@AuraEnabled public Boolean isRequired;
@AuraEnabled public Boolean isReadOnly;
public LayoutField() {}
public LayoutField( Metadata.LayoutItem li ) {
this.fieldName = li.field;
if( li.behavior == Metadata.UiBehavior.Required ) {
this.isRequired = true;
}
else if( li.behavior == Metadata.UiBehavior.ReadOnly ) {
this.isReadOnly = true;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment