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:








Comments

Popular posts from this blog

Configur Docusign For Salesforce

How To Make DataTable Column Resizable

Lightning:recordForm - Lightning Data Service