Here's an approach I've devised a while ago:
<aura:attribute name="recordUiCache" type="Object" access="private" />
<lightning:recordEditForm
density="comfy"
onsuccess="{!c.redirect}"
onsubmit="{!c.showSpinner}"
onload="{!c.hideSpinner}"
onerror="{!c.hideSpinner}"
recordId="{!v.record.Id}"
recordTypeId="{!v.record.RecordTypeId}"
objectApiName="_Info__c">
<lightning:card title="Some Details">
<aura:if isTrue="{!v.showSpinner}">
<lightning:spinner/>
</aura:if>
<aura:set attribute="actions">
<lightning:button
variant="brand"
type="submit"
name="save"
label="Save"/>
</aura:set>
<lightning:messages/>
<lightning:layout>
<lightning:layoutItem padding="around-small">
<lightning:inputField
class="customRequired"
aura:id="requiredField"
fieldName="SomeQuestion1__c"/>
<lightning:inputField
fieldName="SomeOtherQuestion__c"/>
</lightning:layoutItem>
</lightning:layout>
</lightning:card>
</lightning:recordEditForm>
CSS:
.THIS .customRequired {
font-weight: 400;
}
.THIS .customRequired:before {
content: "*";
color: rgb(194, 57, 52);
left: -0.5rem;
position: absolute;
top: 3px;
}
Controller:
hideSpinner: function (component, event, helper) {
component.set('v.recordUiCache', event.getParam('recordUi'));
component.set("v.showSpinner", false);
},
showSpinner: function (component, event, helper) {
var invalidFields = helper.getFieldLabelsByApiName(
component.get('v.recordUiCache'),
helper.getBlankFields(component.find('requiredField')));
if (invalidFields && invalidFields.length > 0) {
helper.reportUserError(
'Please complete all required fields:',
invalidFields.join(', ')
);
event.preventDefault();
return;
}
component.set("v.showSpinner", true);
}
Helper:
getFieldLabelsByApiName: function (recordUi, invalidFields) {
if (recordUi && recordUi.objectInfo && recordUi.objectInfo.fields) {
invalidFields = invalidFields.map(function (value) {
var f = recordUi.objectInfo.fields[value];
if (f) {
return f.label;
} else {
return value;
}
})
}
return invalidFields;
},
getBlankFields: function (fields) {
if(!fields) {
return [];
} else {
if(!$A.util.isArray(fields)){
fields = [fields];
}
}
return fields
.filter(function (i) {
var value = i.get('v.value');
return !value || value == '' || value.trim().length === 0;
})
.map(function (i) {
return i.get('v.fieldName');
});
},
How this works:
- When recordEditForm callback loads, there's a param
recordUI
which holds some metadata info about the form. Store that on component.
- Mark one or more
lightning:inputField
with aura:id="requiredField"
and class="customRequired"
.
- On submit it will look for all required fields, will return blank ones API name's and then will check recordUiCache for their corresponding labels which will be shown as a toast (via
helper.reportUserError
not implemented here).