Hello Everyone, In this tutorial, I am going provide a Lightning Component example that contains inline editing functionality on the Salesforce record. Inline editing lets users quickly edit the field value right on a record's detail pages. So without wasting the time let's get started,
Inline Editing in Lightning Component
For this functionality, I have created two lightning component and an apex class.
Step 1: Login to your Salesforce Org. and open developer console.
Step 2: Go to File>New>Apex Class and Create an Apex controller called InlineEditHandler. Replace following code in apex controller.
InlineEditHandler.apxc
Inline Editing in Lightning Component
For this functionality, I have created two lightning component and an apex class.
Step 1: Login to your Salesforce Org. and open developer console.
Step 2: Go to File>New>Apex Class and Create an Apex controller called InlineEditHandler. Replace following code in apex controller.
InlineEditHandler.apxc
public class InlineEditHandler {
@AuraEnabled
public static List <Account> getAccount() {
List <Account> lstOfAccount = [SELECT id, Name, Rating, website FROM Account LIMIT 5];
return lstOfAccount;
}
@AuraEnabled
public static List <Account> saveAccount(List<Account> lstAccount) {
update lstAccount;
return lstAccount;
}
@AuraEnabled
public static List < String > getselectOptions(sObject objObject, string fld) {
List < String > allOpts = new list < String > ();
Schema.sObjectType objType = objObject.getSObjectType();
Schema.DescribeSObjectResult objDescribe = objType.getDescribe();
MAP < String, Schema.SObjectField > fieldMap = objDescribe.fields.getMap();
List < Schema.PicklistEntry > values = fieldMap.get(fld).getDescribe().getPickListValues();
for (Schema.PicklistEntry a: values) {
allOpts.add(a.getValue());
}
allOpts.sort();
return allOpts;
}
}
Step 3: Go to File>New>Lightning Component and create a Lightning Component called InlineEditChild. Replace the following markup in the Lightning Component.
InlineEditChild.cmp
<aura:component controller="InlineEditHandler">
<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
<aura:attribute name="objInfoForPicklistValues" type="account" default="{sobjectType : 'Account'}" description="object information to fetch picklist values"/>
<aura:attribute name="ratingPicklistOpts" type="string[]" description="store picklist options values"/>
<aura:attribute name="showSaveCancelBtn" type="boolean"/>
<aura:attribute name="showErrorClass" type="boolean" default="false"/>
<aura:attribute name="sNo" type="string" />
<aura:attribute name="nameEditMode" type="boolean" default="false" />
<aura:attribute name="WebsiteEditMode" type="boolean" default="false" />
<aura:attribute name="ratingEditMode" type="boolean" default="false" />
<aura:attribute name="singleRec" type="sobject" default="{'sobjectType' : 'account',
'Name' : '','Website' : '',
'AnnualRevenue' :'','Rating': ''
}"/>
<tr>
<td><div class="slds-truncate">{!v.sNo}</div></td>
<td ondblclick="{!c.inlineEditName}" class="{! v.showErrorClass == true ? 'slds-cell-edit slds-has-error' : 'slds-cell-edit'}">
<span class="slds-grid slds-grid_align-spread">
<!-- show input and output section based on boolean flag -->
<aura:if isTrue="{!v.nameEditMode == false}">
<span class="slds-truncate" title="Name">{!v.singleRec.Name}</span>
<button onclick="{!c.inlineEditName}" class="slds-button slds-button_icon slds-cell-edit__button slds-m-left_x-small" tabindex="0" title="Edit Name">
<lightning:icon iconName="utility:edit" size="xx-small" alternativeText="edit"/>
</button>
<!-- Inline Edit Section in else case-->
<aura:set attribute="else">
<section tabindex="0" class="slds-popover slds-popover_edit" role="dialog" style="position: absolute; top: 0px">
<div class="slds-popover__body">
<div class="slds-form-element slds-grid slds-wrap">
<div class="slds-form-element__control slds-grow">
<ui:inputText class="slds-input inputWidth"
labelClass="slds-form-element__label slds-form-element__label_edit slds-no-flex"
aura:id="inputId"
blur="{!c.closeNameBox}"
change="{!c.onNameChange}"
required="true"
label="Name"
value="{!v.singleRec.Name}" />
</div>
</div>
</div>
<span id="form-end" tabindex="0"></span>
</section>
</aura:set>
</aura:if>
</span>
</td>
<td ondblclick="{!c.inlineEditWebsite}">
<span class="slds-grid slds-grid_align-spread">
<!-- show input and output section based on boolean flag -->
<aura:if isTrue="{!v.WebsiteEditMode == false}">
<span class="slds-truncate" title="Website">{!v.singleRec.Website}</span>
<button onclick="{!c.inlineEditWebsite}" class="slds-button slds-button_icon slds-cell-edit__button slds-m-left_x-small" tabindex="0" title="Edit Website">
<lightning:icon iconName="utility:edit" size="xx-small" alternativeText="edit"/>
</button>
<!-- Inline Edit Section in else case-->
<aura:set attribute="else">
<section tabindex="0" class="slds-popover slds-popover_edit" role="dialog" style="position: absolute; top: 0px">
<div class="slds-popover__body">
<div class="slds-form-element slds-grid slds-wrap">
<div class="slds-form-element__control slds-grow">
<ui:inputText class="slds-input inputWidth"
labelClass="slds-form-element__label slds-form-element__label_edit slds-no-flex"
aura:id="inputWebsiteId"
blur="{!c.closeWebsiteBox}"
change="{!c.onWebsiteChange}"
label="Website"
value="{!v.singleRec.Website}" />
</div>
</div>
</div>
<span id="form-end" tabindex="0"></span>
</section>
</aura:set>
</aura:if>
</span>
</td>
<td ondblclick="{!c.inlineEditRating}">
<span class="slds-grid slds-grid_align-spread">
<!-- show input and output section based on boolean flag -->
<aura:if isTrue="{!v.ratingEditMode == false}">
<span class="slds-truncate" title="Rating">{!v.singleRec.Rating}</span>
<button onclick="{!c.inlineEditRating}" class="slds-button slds-button_icon slds-cell-edit__button slds-m-left_x-small" tabindex="0" title="Edit Rating">
<lightning:icon iconName="utility:edit" size="xx-small" alternativeText="edit"/>
</button>
<!-- Inline Edit Section in else case-->
<aura:set attribute="else">
<section tabindex="0" class="slds-popover slds-popover_edit" role="dialog" style="position: absolute; top: 0px;width:80%">
<div class="slds-popover__body">
<div class="slds-form-element slds-grid slds-wrap">
<div class="slds-form-element__control slds-grow">
<label class="slds-form-element__label">Rating</label>
<ui:inputSelect aura:id="accRating"
class="slds-select inputRatingWidth"
blur="{!c.closeRatingBox}"
change="{!c.onRatingChange}"
value="{!v.singleRec.Rating}"
/>
</div>
</div>
</div>
<span id="form-end" tabindex="0"></span>
</section>
</aura:set>
</aura:if>
</span>
</td>
</tr>
</aura:component>
InlineEditChildController.js
({
doInit: function(component, event, helper) {
helper.fetchPickListVal(component, 'Rating', 'ratingPicklistOpts');
},
inlineEditName : function(component,event,helper){
component.set("v.nameEditMode", true);
setTimeout(function(){
component.find("inputId").focus();
}, 100);
},
inlineEditWebsite : function(component,event,helper){
component.set("v.WebsiteEditMode", true);
setTimeout(function(){
component.find("inputWebsiteId").focus();
}, 100);
},
inlineEditRating : function(component,event,helper){
component.set("v.ratingEditMode", true);
component.find("accRating").set("v.options" , component.get("v.ratingPicklistOpts"));
setTimeout(function(){
component.find("accRating").focus();
}, 100);
},
onNameChange : function(component,event,helper){
if(event.getSource().get("v.value").trim() != ''){
component.set("v.showSaveCancelBtn",true);
}
},
onWebsiteChange : function(component,event,helper){
if(event.getSource().get("v.value").trim() != ''){
component.set("v.showSaveCancelBtn",true);
}
},
onRatingChange : function(component,event,helper){
component.set("v.showSaveCancelBtn",true);
},
closeNameBox : function (component, event, helper) {
component.set("v.nameEditMode", false);
if(event.getSource().get("v.value").trim() == ''){
component.set("v.showErrorClass",true);
}
else{
component.set("v.showErrorClass",false);
}
},
closeWebsiteBox : function (component, event, helper) {
component.set("v.WebsiteEditMode", false);
},
closeRatingBox : function (component, event, helper) {
component.set("v.ratingEditMode", false);
},
})
InlineEditChildHelper.js ({
fetchPickListVal: function(component, fieldName, picklistOptsAttributeName) {
var action = component.get("c.getselectOptions");
action.setParams({
"objObject": component.get("v.objInfoForPicklistValues"),
"fld": fieldName
});
var opts = [];
action.setCallback(this, function(response) {
if (response.getState() == "SUCCESS") {
var allValues = response.getReturnValue();
if (allValues != undefined && allValues.length > 0) {
opts.push({
class: "optionClass",
label: "--- None ---",
value: ""
});
}
for (var i = 0; i < allValues.length; i++) {
opts.push({
class: "optionClass",
label: allValues[i],
value: allValues[i]
});
}
component.set("v." + picklistOptsAttributeName, opts);
}
});
$A.enqueueAction(action);
},
})
InlineEditChildStyle.css .THIS .inputWidth {
width:80%;
}
.THIS .inputRatingWidth {
width:75%;
}
Step 4: Go to File>New>Lightning Component and create a Lightning Component called InlineEdit. Replace the following markup in the Lightning Component.InlineEdit.cmp
<aura:component controller="InlineEditHandler" implements="flexipage:availableForAllPageTypes,force:hasRecordId,force:appHostable">
<aura:handler name="init" value="{!this}" action="{!c.initRecords}"/>
<aura:attribute name="AccountList" type="account[]" description="store account records list"/>
<aura:attribute name="showSaveCancelBtn" type="boolean" default="false" description="flag for rendered save and cancel buttons in aura:if "/>
<br/><center style="font-size:16px;font-weight:bold;"><u>Edit Account Records</u></center><br/>
<table class="slds-table slds-table_bordered slds-table_cell-buffer">
<thead>
<tr class="slds-text-title--caps">
<th scope="col"><div class="slds-truncate" title="Id">S.No</div></th>
<th scope="col"><div class="slds-truncate" title="Account Name">Account Name</div></th>
<th scope="col"><div class="slds-truncate" title="Website">Website</div></th>
<th scope="col"><div class="slds-truncate" title="Rating">Rating</div></th>
</tr>
</thead>
<tbody>
<!--### display all records of AccountList attribute one by one by aura:iteration ###-->
<aura:iteration items="{!v.AccountList}" var="acc" indexVar="sNo">
<!-- Child Lightning Component -->
<c:InlineEditChild singleRec="{!acc}" showSaveCancelBtn="{!v.showSaveCancelBtn}" sNo="{!sNo + 1}" />
</aura:iteration>
</tbody>
</table>
<br/>
<center>
<!-- use aura:if for show/hide buttons -->
<aura:if isTrue="{!v.showSaveCancelBtn}">
<!--button for save and cancel Record after Inline Edit-->
<lightning:button label="Cancel" onclick="{!c.cancel}"/>
<lightning:button label="Save" onclick="{!c.Save}" variant="success"/>
</aura:if>
</center>
</aura:component>
InlineEditController.js ({
initRecords: function(component, event, helper) {
var action = component.get("c.getAccount");
action.setCallback(this, function(response) {
var state = response.getState();
if (state === "SUCCESS") {
var storeResponse = response.getReturnValue();
component.set("v.AccountList", storeResponse);
}
});
$A.enqueueAction(action);
},
Save: function(component, event, helper) {
if (helper.requiredValidation(component, event)){
var action = component.get("c.saveAccount");
action.setParams({
'lstAccount': component.get("v.AccountList")
});
action.setCallback(this, function(response) {
var state = response.getState();
if (state === "SUCCESS") {
var storeResponse = response.getReturnValue();
component.set("v.AccountList", storeResponse);
component.set("v.showSaveCancelBtn",false);
alert('Record Updated');
}
});
$A.enqueueAction(action);
}
},
cancel : function(component,event,helper){
$A.get('e.force:refreshView').fire();
}
})
InlineEditHelper.js ({
requiredValidation : function(component,event) {
var allRecords = component.get("v.AccountList");
var isValid = true;
for(var i = 0; i < allRecords.length;i++){
if(allRecords[i].Name == null || allRecords[i].Name.trim() == ''){
alert('Complete this field : Row No ' + (i+1) + ' Name is null' );
isValid = false;
}
}
return isValid;
}
})
To see the output of this Lightning component create a Lightning Component tab (Setup | Create | Tabs | Lightning Component Tabs), then switch your Salesforce org in Lightning experience and click on the tab that you created earlier for this component.Output:
See also:
- Send Email Lightning Component
- Email Field Validation in Lightning Component
- $Locale in Lightning Component
Conclusion:
Hope you like this tutorial, for any query or suggestions
please feel free to comment.
Thank you.
9 Comments
nice blog and realy helpful
ReplyDeletethanks a lot..!
Deletegreat! realy helpful
ReplyDeleteglad to know, it's helpful for you.!
Delete
ReplyDeleteThank you so much for sharing all this wonderful info with the how-to’s!!!! It is so appreciated! Cheers!!
Thanks
DeleteHi
ReplyDeleteI am getting focus() not a function error , can anyone help?
I think, you have to set your component version to lower.
DeleteHi Manish, do you know if it will work for inline editing rich text fields?
ReplyDeletePost a Comment