wissel.net

Usability - Productivity - Business - The web - Singapore & Twins

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 the layoutType attribute. It can't be empty or anything else than Compact or Full. 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 on 06 November 2018 | Comments (0) | categories: Lightning Salesforce

Comments

  1. No comments yet, be the first to comment