Lightning Mini Forms
One of my favorite lightning features is the Lightning App Builder. It allows to tailor Salesforce for a given set of users, to show what they need, how they need it.
In the page editor the endless scrolling page, record details followed by related lists, we got to love, can be broken down into multiple tabs. For related lists, the OOTB controls already allow to just pick one. Placed multiple times on a page, the layout can fit a specific audience's precise need, avoiding information overload.
However there's no control to break down the record details. The OOTB record details control will faithfully reproduce the assigned page layout with all sections. Custom controls to the rescue!
Design options
There are two options to consider: where to pull design information from and how to render it. For the later you can consider lightning:recordEdit|ViewForm or lightning:recordForm. Both can be argued for.
The lightning:recordForm
only needs the fields / layout options supplied and will take care of all rendering. However you are limited to one or two columns - just like page layouts.
The lightning:record[Edit|View]Form
requires coding the fields, probably using an aura:iteration, but leaves you with the freedom of layout. Typically you would use a lightning:layoutItem and its size
property to determine the number of columns (with 12 / size = number of columns).
To keep it simple I'll stick to the lightning:recordForm
for now.
Next question: where to provision the list of fields from? When you want an universally usable mini form, you can't hardcode them, but provide them using a design property, so they can be provided in the page editor after you dragged the component onto the page.
Still you need to decide what attributes you provide:
- List of field names
- Name of a field set
- Name of a section in a page layout
I'll start with the first one and relegate the other two approaches to future posts.
To make this work you will need a custom lightning component. Let's call it MiniForm
. We will only need MiniForm.cmp
, MiniFormController.js
and MiniForm.design
. No helper or Apex will be harmed
The component looks like this:
<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId"
access="global">
<aura:attribute name="recordId"
type="Id"
default=""
description="Account Record Id" />
<aura:attribute name="objectType"
type="String"
default="Account"
description="Sobject Name" />
<aura:attribute name="fieldList"
type="String"
description="Fields to show" />
<aura:attribute name="fieldListArray"
type="String[]"
default="Id,Name"
access="private" />
<aura:attribute name="columns"
type="String"
default="1"
description="Column count one or two" />
<aura:attribute name="layoutType"
type="String"
default="Full" />
<aura:attribute name="formReady"
type="Boolean"
default="false"
access="private" />
<aura:handler name="init"
action="{!c.doInit}"
value="{!this}" />
<lightning:card>
<aura:if isTrue="{!v.formReady}">
<div class="slds-p-horizontal_small">
<lightning:recordForm
aura:id="MiniForm"
recordId="{!v.recordId}"
objectApiName="{!v.objectType}"
fields="{!v.fieldListArray}"
columns="{!v.columns}"
mode="view" />
</div>
</aura:if>
</lightning:card>
</aura:component>
There are a few caveats, I'll highlight below
The design file will determine what is visible in the page designer. Currently that information is static, so the Awesome Admin needs to be extra careful not to mistype anything.
<design:component label="Mini Form">
<design:attribute name="layoutType"
label="Fields from Layout"
description="Should the fields from the full or compact layout be used"
default="Full"
datasource="Empty,Full,Compact"/>
<design:attribute name="fieldList"
label="additional Fields"
description="Fields to be shown in addition to layout (if any)"
default="Name,Id"/>
<design:attribute name="objectType"
label="Object"
description="Which object"
default="Account"/>
<design:attribute name="columns"
label="1/2 columns"
description="one or two"
default="1"
datasource="1,2" />
</design:component>
The final piece it the JavaScript controller:
({
doInit : function(component, event, helper) {
const layoutType = component.get('v.layoutType');
// Set the layout type if we have one
if (layoutType === 'Compact' || layoutType === 'Full') {
const miniForm = component.find('MiniForm');
miniForm.set('v.layoutType', layoutType);
}
const fieldList = component.get('v.fieldList').split(',');
component.set('v.fieldListArray', fieldList);
component.set('v.formReady', true);
}
})
You can now use the component on a page layout. In addition to specify the fields, it allows to use the predefined main or compact layout. You also can embed it into your own components. You then would need to specify the attributes you need:
<c:MiniForm recordId="{!v.recordId}" objectType="Contact" layoutType="none" />
This would show the Name and Id field in one column - based on the default settings.
Lessons learned
- Always use defaults in the component. This makes it easier when embedding. Specifying defaults in the design properties isn't enough
lightning:recordForm
is particular about thelayoutType
attribute. It can't be empty or anything else thanCompact
orFull
. That's the reason why the attribute isn't in the markup but gets (eventually) added in the controller- The design definition doesn't allow for a String array. To mitigate that the
onInit
function splits the design provided String into an array. The array is private not to disturb that mechanism. You might consider adding a method that allows to change the values in code - Timing is everything. That's why the form is enclosed by an
aura:if
that will render only after the values have been set. While that doesn't seem a problem in an aura-less controller, it might bite you in heavy load pages, so better save than sorry
A variation of this approach: instead of using a design time property in the page editor, supply the field names through a lookup into a custom meta data record. This would allow to alter the fields shown based on some lookup logic. However you would need an Apex controller for that.
Next stop: instead of a field list supply a section name or a fieldset name
As usual YMMV
Posted by Stephan H Wissel on 06 November 2018 | Comments (0) | categories: Lightning Salesforce