Using Lightning Data Service in Action Overrides

Introduction:-

In this blog post, I am going to explain how to use the Lightning data services in Lightning component standard action overrides.  Use Lightning Data Service to load, create, edit, or delete a record in your component without requiring Apex code. Lightning Data Service handles sharing rules and field-level security for you.  Lightning Data Service as the Lightning Components version of the Visualforce standard controller. To override the standard action with lightning component, the component must implements lightning:actionOverride interface.
<aura:component implements="force:appHostable,force:hasRecordId,lightning:actionOverride" access="global" >
    <aura:attribute name="newWorkOrder" type="Object"/>
    <aura:attribute name="newWorkOrderRecord" type="Object"/>
    <aura:attribute name="newWorkOrderError" type="String"/>
    
    <force:recordData aura:id="newWorkOrderRecordId"
                      layoutType="FULL"
                      mode="EDIT"
                      targetRecord="{!v.newWorkOrder}"
                      targetFields="{!v.newWorkOrderRecord}"
                      targetError="{!v.newWorkOrderError}"
                      />
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    <div class="New WorkOrder Details ">
        <lightning:card iconName="action:custom84_120" title="Create New WorkOrder">
            <div class="slds-p-horizontal--large">
               
               
                <lightning:input aura:id="workOrderIds" label="Status" value="{!v.newWorkOrderRecord.Status}"/>
                <lightning:input aura:id="workOrderIds"  label="Priority" value="{!v.newWorkOrderRecord.Priority}"/>
                <lightning:input aura:id="workOrderIds" label="Subject" value="{!v.newWorkOrderRecord.Subject}"/>
                <lightning:input aura:id="workOrderIds" label="Description" value="{!v.newWorkOrderRecord.Description}"/>
                <br/>
                <lightning:button label="Save" variant="brand" onclick="{!c.handleSave}"/>
                
            </div>
        </lightning:card>
    </div>
    
    <aura:if isTrue="{!not(empty(v.newWorkOrderError))}">
        <div class="recordError">
            {!v.newWorkOrderError}</div>
    </aura:if>
    
    
</aura:component>
({
    doInit: function(component, event, helper) {
        // Prepare a new record from template
        component.find("newWorkOrderRecordId").getNewRecord(
            "WorkOrder", // sObject type (entityAPIName)
            null,      // recordTypeId
            false,     // skip cache?
            $A.getCallback(function() {
                var record = component.get("v.newWorkOrder");
                var error = component.get("v.newWorkOrderError");
                if(error || (record === null)) {
                    console.log("Error initializing record template: " + error);
                }
                else {
                    console.log("Record template initialized: " + record);
                }
            })
        );
    },
    
    handleSave: function(component, event, helper) {
        component.find("newWorkOrderRecordId").saveRecord(function(saveResult) {
            if (saveResult.state === "SUCCESS" || saveResult.state === "DRAFT") {
                // record is saved successfully
                var resultsToast = $A.get("e.force:showToast");
                resultsToast.setParams({
                    "title": "Saved",
                    "message": "The record was saved."
                });
                resultsToast.fire();
                $A.get("e.force:refreshView").fire();   
                
                
            } else if (saveResult.state === "INCOMPLETE") {
                // handle the incomplete state
                console.log("User is offline, device doesn't support drafts.");
            } else if (saveResult.state === "ERROR") {
                // handle the error state
                console.log('Problem saving contact, error: ' + 
                            JSON.stringify(saveResult.error));
            } else {
                console.log('Unknown problem, state: ' + saveResult.state +
                            ', error: ' + JSON.stringify(saveResult.error));
            }
        });
        
    }
})

Override Edit Action 

To override the edit action you need to implement lightning: actionOverride interface and update the record using Lightning Data Service by calling saveRecord on the force:recordData component, and pass in a callback function to be invoked after the save operation completes.

<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId,lightning:actionOverride">
    
    <aura:attribute name="workorderrecord" type="Object"/>
    <aura:attribute name="workordeksimpleRecord" type="Object"/>
    <aura:attribute name="recordError" type="String"/>
    
    <force:recordData aura:id="recordHandler"
                      recordId="{!v.recordId}"
                      layoutType="FULL"
                      targetRecord="{!v.workorderrecord}"
                      targetFields="{!v.workordeksimpleRecord}"
                      targetError="{!v.recordError}"
                      mode="EDIT"
                      recordUpdated="{!c.handleRecordUpdated}"
                      />
    
    <!-- Display a header with details about the record -->
    <div class="slds-page-header" role="banner">
        <p class="slds-text-heading_label">Edit Record</p>
        <h1 class="slds-page-header__title slds-m-right_small
                   slds-truncate slds-align-left">{!v.workordeksimpleRecord.Name}</h1>
    </div>
    
    <!-- Display Lightning Data Service errors, if any -->
    <aura:if isTrue="{!not(empty(v.recordError))}">
        <div class="recordError">
            <ui:message title="Error" severity="error" closable="true">
                {!v.recordError}
            </ui:message>
        </div>
    </aura:if>
    
    <!-- Display an editing form -->
    <lightning:input aura:id="recordName"  label="Status"
                     value="{!v.workordeksimpleRecord.Status}" />
    <lightning:input aura:id="recordName"  label="Description"
                     value="{!v.workordeksimpleRecord.Description}" />
    
    <lightning:input aura:id="recordName"  label="Subject"
                     value="{!v.workordeksimpleRecord.Subject}" />
    
    
    <lightning:button label="Save Record" onclick="{!c.handleSaveRecord}"
                      variant="brand" class="slds-m-top_medium"/>
</aura:component>

 

({
    handleSaveRecord: function(component, event, helper) {
        component.find("recordHandler").saveRecord($A.getCallback(function(saveResult) {
            // NOTE: If you want a specific behavior(an action or UI behavior) when this action is successful 
            // then handle that in a callback (generic logic when record is changed should be handled in recordUpdated event handler)
            if (saveResult.state === "SUCCESS" || saveResult.state === "DRAFT") {
                // handle component related logic in event handler
            } else if (saveResult.state === "INCOMPLETE") {
                console.log("User is offline, device doesn't support drafts.");
            } else if (saveResult.state === "ERROR") {
                console.log('Problem saving record, error: ' + JSON.stringify(saveResult.error));
            } else {
                console.log('Unknown problem, state: ' + saveResult.state + ', error: ' + JSON.stringify(saveResult.error));
            }
        }));
    },
    
    /**
     * Control the component behavior here when record is changed (via any component)
     */
    handleRecordUpdated: function(component, event, helper) {
        var eventParams = event.getParams();
        if(eventParams.changeType === "CHANGED") {
            // get the fields that changed for this record
            var changedFields = eventParams.changedFields;
            console.log('Fields that are changed: ' + JSON.stringify(changedFields));
            // record is changed, so refresh the component (or other component logic)
            var resultsToast = $A.get("e.force:showToast");
            resultsToast.setParams({
                "title": "Saved",
                "message": "The record was updated."
            });
            resultsToast.fire();
            
        } else if(eventParams.changeType === "LOADED") {
            // record is loaded in the cache
        } else if(eventParams.changeType === "REMOVED") {
            // record is deleted and removed from the cache
        } else if(eventParams.changeType === "ERROR") {
            // there’s an error while loading, saving or deleting the record
        }
    }
})

Override View Action

To override the edit action you need to implement lightning: actionOverride interface and Loading a data by using the Lightning Data Service.  To load a record using Lightning Data Service, add the force:recordData tag to your component. In the force:recordDatatag, specify the ID of the record to be loaded, a list of fields, and the attribute to which to assign the loaded record. 
<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId,lightning:actionOverride">
    
    <aura:attribute name="workOrderRec" type="Object"/>
    <aura:attribute name="simpleworkOrderRec" type="Object"/>
    <aura:attribute name="workOrderError" type="String"/>
    
    <force:recordData aura:id="recordLoader"
                      recordId="{!v.recordId}"
                      layoutType="FULL"
                      targetRecord="{!v.workOrderRec}"
                      targetFields="{!v.simpleworkOrderRec}"
                      targetError="{!v.workOrderError}"
                      recordUpdated="{!c.handleRecordUpdated}"
                      />
    
    <!-- Display a header with details about the record -->
    <div class="slds-page-header" role="banner">
        <h1 class="slds-page-header__title slds-m-right_small
                   slds-truncate slds-align-left">Work Order Details </h1>
        <p class="slds-text-heading_label">{!v.simpleworkOrderRec.WorkOrderNumber}</p>
    </div>
    
    <!-- Display Lightning Data Service errors, if any -->
    <aura:if isTrue="{!not(empty(v.workOrderError))}">
        <div class="recordError">
            <ui:message title="Error" severity="error" closable="true">
                {!v.workOrderError}
            </ui:message>
        </div>
    </aura:if>
    
    <lightning:recordViewForm recordId="{!v.recordId}" objectApiName="WorkOrder">
        
        <div class="slds-box slds-theme_default">
            
            <lightning:outputField fieldName="Case"/>
            <lightning:outputField fieldName="Description" />
            <lightning:outputField fieldName="Duration" />
            <lightning:outputField fieldName="Priority" />
            <lightning:outputField fieldName="StartDate" />
            <lightning:outputField fieldName="Status" />
            <lightning:outputField fieldName="Subject" />
            
            <lightning:outputField fieldName="TotalPrice" />
            <lightning:outputField fieldName="EndDate" />
        </div>
    </lightning:recordViewForm>
</aura:component>

 

({
    handleRecordUpdated: function(component, event, helper) {
        var eventParams = event.getParams();
        if(eventParams.changeType === "LOADED") {
            // record is loaded (render other component which needs record data value)
            console.log("Record is loaded successfully.");
        } else if(eventParams.changeType === "CHANGED") {
            // record is changed
        } else if(eventParams.changeType === "REMOVED") {
            // record is deleted
        } else if(eventParams.changeType === "ERROR") {
            // there’s an error while loading, saving, or deleting the record
        }
    }
})