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