Let's say you have a requirement that you want to create a related object record from a target records detail page. You also want to do some pre-validation and pre-populate fields on the related object record as guidelines for user suggestion.
In Salesforce Classic one way you could have done it was using an OnClick JavaScript button and include it on the target record's page layout. The picture below shows an implementation of a javascript button to accomplish the above requirement. The other way involves create a custom visualforce page and doing the validation on there and based on the complexity of the validation maybe need a controller to query related record fields. So it wasn't a very hard choice in Salesforce classic to go with the OnClick Javascript option.
Lightning Quick Action Implementation (Github)
In the lightning experience we cannot use OnClick Javascript buttons due to compatibility issues with lightning navigation so in this blog I am suggesting an approach I have used to use the replicate the above functionality using Quick Actions and lightning components. Also to make reuse of some of the functionality we have encapsulated the redirection logic into its own lightning component so it can be used in multiple quick action components. Due to the complexity of the pre-validation logic it is best if that is kept in the parent quick action component and keep the redirect component implementation light.
CustomRedirect Component
Encapsulates the redirect functionality to be reused in other quick action components and provides a reusable interface to redirect to create or edit any sobject records with pre-populated values.
<aura:component description="Custom Redirect Quick Action for replacing common standard page redirects for javascript button">
<!--Global ATTRIBUTES-->
<aura:attribute name="sObjectApiName" type="String" access="public" required="true"/>
<aura:attribute name="mode" type="String" access="public" required="true"/>
<aura:attribute name="recordId" type="String" access="public"/>
<aura:attribute name="defaultFieldValuePairs" type="String" access="public"/>
<aura:attribute name="showError" type="Boolean" access="public"/>
<aura:attribute name="errorMessage" type="String" access="public"/>
<!--Private ATTRIBUTES-->
<aura:attribute name="loading" type="Boolean" />
<!--Events-->
<aura:registerEvent name="redirectDone" type="c:CustomRedirectDone"/>
<!--HANDLERS-->
<aura:handler name="init" action="{!c.doInit}" value="{!this}"/>
<!--ERROR MSG-->
<aura:if isTrue="{!v.showError}">
<div class="slds-box slds-notify_alert slds-theme_alert-texture slds-theme_error" role="alert">
<span class="slds-assistive-text">error</span>
<span class="slds-icon_container slds-icon-utility-error slds-m-right_x-small" title="Description of icon when needed">
<lightning:icon iconName="utility:error" size="medium"
alternativeText="error" class="iconContainer" />
</span>
<h2>{!v.errorMessage}</h2>
</div>
</aura:if>
<!--</div>-->
</aura:component>
CustomRedirectController.js
({
doInit : function(component, event, helper) {
helper.doRedirect(component, event, helper);
}
})
CustomRedirectHelper.js
({
doRedirect : function(component, event, helper) {
var showError = component.get('v.showError');
var mode = component.get('v.mode');
var redirectDoneEvent = component.getEvent('redirectDone');
redirectDoneEvent.setParams({"isSuccess": false, "message": "Error message shown."});
if(showError === undefined || showError === false) {
var sObjectApiName = component.get('v.sObjectApiName');
var defaultValues = component.get('v.defaultFieldValuePairs');
switch(mode) {
case 'CREATE':
var createRecordEvent = $A.get("e.force:createRecord");
createRecordEvent.setParams({
"entityApiName": sObjectApiName,
"defaultFieldValues": defaultValues
});
createRecordEvent.fire();
redirectDoneEvent.setParams({"isSuccess": true, "message": "Redirected to create record successfully!"});
break;
case 'EDIT':
var editRecordEvent = $A.get("e.force:editRecord");
editRecordEvent.setParams({
"recordId": component.get("v.recordId"),
"defaultFieldValues": defaultValues
});
editRecordEvent.fire();
redirectDoneEvent.setParams({"isSuccess": true, "message": "Redirected to edit record successfully!"});
break;
default:
redirectDoneEvent.setParams({"isSuccess": false, "message": "Invalid mode specified for redirect component!"});
break;
}
}
redirectDoneEvent.fire();
},
})
CustomRedirectDone Event
Event fired on success or error from the CustomRedirect component can be handled by the parent component to take appropriate action. One action is to close the quick action on success (as it will redirect to the edit or create component).
CustomRedirectDone.evt
<aura:event type="COMPONENT">
<aura:attribute name="isSuccess" type="Boolean"/>
<aura:attribute name="message" type="String"/>
</aura:event>
Demo Usage
Sample usage and demo on account to create a contact with some basic pre-validation. Since the pre-validation logic is still part of the parent quick action component. This can be embellished to be as complex as desired.
ContactRedirectDemo.cmp
<aura:component description="ContactRedirectDemo"
implements="force:lightningQuickAction,force:hasRecordId">
<aura:attribute name="showCreateContact" type="Boolean" default="false"/>
<aura:attribute name="defaultValues" type="String" />
<aura:attribute name="showError" type="Boolean"/>
<aura:attribute name="errorMessage" type="String"/>
<aura:attribute name="recordId" type="String"/>
<aura:attribute name="record" type="Account"/>
<aura:handler name="redirectDone" event="c:CustomRedirectDone"
action="{!c.handleRedirectDone}"/>
<force:recordData aura:id="recordLoader"
recordId="{!v.recordId}"
targetFields="{!v.record}"
fields="['Id',
'Name',
'Industry',
'Type',
'Phone',
'BillingStreet',
'BillingCity',
'BillingState',
'BillingPostalCode',
'BillingCountry']"
mode="VIEW"
recordUpdated="{!c.doRedirect}"/>
<aura:if isTrue="{!v.showCreateContact}">
<c:CustomRedirect sObjectApiName="Contact"
mode="CREATE"
showError="{!v.showError}"
errorMessage="{!v.errorMessage}"
defaultFieldValuePairs="{!v.defaultValues}"/>
</aura:if>
</aura:component>
ContactRedirectDemoController.js
({
doRedirect : function(component, event, helper) {
//Get Account Record
var account = component.get("v.record");
if(account.Industry === "Consulting" && account.Type == 'Customer - Direct') {
var defaultValues = {};
defaultValues.Phone = account.Phone;
defaultValues.MailingStreet = account.BillingStreet;
defaultValues.MailingCity = account.BillingCity;
defaultValues.MailingPostalCode = account.BillingPostalCode;
defaultValues.MailingState = account.BillingState;
defaultValues.MailingCountry = account.BillingCountry;
defaultValues.AccountId = account.Id;
component.set("v.defaultValues", defaultValues);
} else {
component.set("v.showError", true);
component.set("v.errorMessage", 'Only available on consulting accounts.');
}
//Show redirect component
component.set("v.showCreateContact", true);
},
handleRedirectDone : function(component, event, helper) {
var isSuccess = event.getParam("isSuccess");
var message = event.getParam("message");
console.log("handleRedirectDone-> isSuccess:" + isSuccess + " message: " + message);
if(isSuccess === true) {
// Close the action panel if not error
var dismissActionPanel = $A.get("e.force:closeQuickAction");
dismissActionPanel.fire();
}
}
})
Comments