Inline Edit And Custom Lightning Components
Inline Editing lets users quickly edit field values, right on a record's detail pages.
Below are the Custom Lightning Components support Inline Editing.
Apex Controller:
public class InlineEditController {
@AuraEnabled
public static List <account> fetchAccount() {
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) {
system.debug('objObject --->' + objObject);
system.debug('fld --->' + 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;
}
}
Child Component:
<aura:component controller="InlineEditController">
<!-- on component load, fetch picklist values dynamically from apex controller -->
<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
<!--declare aura attributes-->
<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="singleRec" type="sobject" default="{'sobjectType' : 'account',
'Name' : '',
'Website' : '',
'AnnualRevenue' :'',
'Rating': ''
}"/>
<aura:attribute name="nameEditMode" type="boolean" default="false" />
<aura:attribute name="ratingEditMode" type="boolean" default="false" />
<!--Table Row Start-->
<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 inputFieldWidth"
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>
<div class="slds-truncate">{!v.singleRec.Website}</div>
</td>
<td ondblclick="{!c.inlineEditRating}" class="slds-cell-edit">
<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">
<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 inputFieldWidth"
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>
JavaScript Controller:
({
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);
},
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);
}
},
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);
}
},
closeRatingBox : function (component, event, helper) {
component.set("v.ratingEditMode", false);
},
})
JavaScript Helper:
({
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);
},
})
CSS Style:
.THIS .inputFieldWidth {
width:85%;
}
Parent Component:
<aura:component controller="InlineEditController" implements="flexipage:availableForAllPageTypes,force:hasRecordId,force:appHostable">
<!--Init handler which is call initRecords js function on component Load-->
<aura:handler name="init" value="{!this}" action="{!c.initRecords}"/>
<!--declare aura attributes-->
<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 "/>
<div class="slds-m-around_large">
<!-- use aura:if for show/hide buttons -->
<aura:if isTrue="{!v.showSaveCancelBtn}">
<!--button for save and cancel Record after Inline Edit-->
<lightning:buttonGroup class="slds-m-around_medium">
<lightning:button label="Cancel" onclick="{!c.cancel}"/>
<lightning:button label="Save" onclick="{!c.Save}" variant="success"/>
</lightning:buttonGroup>
</aura:if>
<!--Data Table-->
<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:InlineRdit singleRec="{!acc}"
showSaveCancelBtn="{!v.showSaveCancelBtn}"
sNo="{!sNo + 1}" />
</aura:iteration>
</tbody>
</table>
</div>
</aura:component>
JavaScript Controller:
({
initRecords: function(component, event, helper) {
var action = component.get("c.fetchAccount");
action.setCallback(this, function(response) {
var state = response.getState();
if (state === "SUCCESS") {
var storeResponse = response.getReturnValue();
console.log(JSON.stringify(storeResponse));
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('Updated...');
}
});
$A.enqueueAction(action);
}
},
cancel : function(component,event,helper){
$A.get('e.force:refreshView').fire();
}
})
JavaScript Helper:
({
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;
}
})
OutCome:
Below are the Custom Lightning Components support Inline Editing.
Apex Controller:
public class InlineEditController {
@AuraEnabled
public static List <account> fetchAccount() {
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) {
system.debug('objObject --->' + objObject);
system.debug('fld --->' + 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;
}
}
Child Component:
<aura:component controller="InlineEditController">
<!-- on component load, fetch picklist values dynamically from apex controller -->
<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
<!--declare aura attributes-->
<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="singleRec" type="sobject" default="{'sobjectType' : 'account',
'Name' : '',
'Website' : '',
'AnnualRevenue' :'',
'Rating': ''
}"/>
<aura:attribute name="nameEditMode" type="boolean" default="false" />
<aura:attribute name="ratingEditMode" type="boolean" default="false" />
<!--Table Row Start-->
<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 inputFieldWidth"
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>
<div class="slds-truncate">{!v.singleRec.Website}</div>
</td>
<td ondblclick="{!c.inlineEditRating}" class="slds-cell-edit">
<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">
<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 inputFieldWidth"
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>
JavaScript Controller:
({
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);
},
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);
}
},
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);
}
},
closeRatingBox : function (component, event, helper) {
component.set("v.ratingEditMode", false);
},
})
JavaScript Helper:
({
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);
},
})
CSS Style:
.THIS .inputFieldWidth {
width:85%;
}
Parent Component:
<aura:component controller="InlineEditController" implements="flexipage:availableForAllPageTypes,force:hasRecordId,force:appHostable">
<!--Init handler which is call initRecords js function on component Load-->
<aura:handler name="init" value="{!this}" action="{!c.initRecords}"/>
<!--declare aura attributes-->
<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 "/>
<div class="slds-m-around_large">
<!-- use aura:if for show/hide buttons -->
<aura:if isTrue="{!v.showSaveCancelBtn}">
<!--button for save and cancel Record after Inline Edit-->
<lightning:buttonGroup class="slds-m-around_medium">
<lightning:button label="Cancel" onclick="{!c.cancel}"/>
<lightning:button label="Save" onclick="{!c.Save}" variant="success"/>
</lightning:buttonGroup>
</aura:if>
<!--Data Table-->
<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:InlineRdit singleRec="{!acc}"
showSaveCancelBtn="{!v.showSaveCancelBtn}"
sNo="{!sNo + 1}" />
</aura:iteration>
</tbody>
</table>
</div>
</aura:component>
JavaScript Controller:
({
initRecords: function(component, event, helper) {
var action = component.get("c.fetchAccount");
action.setCallback(this, function(response) {
var state = response.getState();
if (state === "SUCCESS") {
var storeResponse = response.getReturnValue();
console.log(JSON.stringify(storeResponse));
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('Updated...');
}
});
$A.enqueueAction(action);
}
},
cancel : function(component,event,helper){
$A.get('e.force:refreshView').fire();
}
})
JavaScript Helper:
({
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;
}
})
OutCome:
Comments
Post a Comment