Skip to content

Instantly share code, notes, and snippets.

@sfcure
Last active April 18, 2021 07:12
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save sfcure/845a0e75815f7c0d6c92baebcce5bc3d to your computer and use it in GitHub Desktop.
Save sfcure/845a0e75815f7c0d6c92baebcce5bc3d to your computer and use it in GitHub Desktop.
This is a working example of rendering Lightning:RecordEditForm dynamically as per object's page layout
<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 LightningRecordEditFormController {
@AuraEnabled
public static List<LayoutSection> getPageLayoutFields() {
List<LayoutSection> lstSections = new List<LayoutSection>();
try {
// Provide the page layout name here
// You can give multiple page layout names here as well
List<String> componentNameList = new List<String>{'Contact-Contact Layout'};
// 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 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;
}
}
}
}
({
doInit: function( component, event, helper ) {
var action = component.get("c.getPageLayoutFields");
action.setCallback(this, function(response) {
var state = response.getState();
if (state === "SUCCESS") {
component.set("v.layoutSections", response.getReturnValue() );
console.log( response.getReturnValue() );
}
else if (state === "INCOMPLETE") {
}
else if (state === "ERROR") {
var errors = response.getError();
console.log( errors );
}
});
$A.enqueueAction(action);
},
handleSuccess : function(component, event, helper) {
var toastEvent = $A.get("e.force:showToast");
toastEvent.setParams({
"title": "Success!",
"message": "The property's info has been updated.",
"type": "success"
});
toastEvent.fire();
},
handleLoad : function(component, event, helper) {
component.set("v.showSpinner", false);
},
handleSubmit : function(component, event, helper) {
}
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment